首页 > 其他分享 >[JOISC 2023 Day3] Tourism

[JOISC 2023 Day3] Tourism

时间:2024-08-10 10:06:57浏览次数:7  
标签:return int siz odt Day3 JOISC go Tourism dis

虚树大小可以从两个角度进行思考:

最小斯坦纳树大小,或者,子树内至少有一个标记点的点的数量减去虚树上边的点的数量。

前者的优点是简洁,后者的优点是不依赖 dfn 序的排序。

这道题在利用后者的同时,将赋值看作了颜色段,用树链剖分保证了颜色段总数为 \(O(n\log n)\),利用了 odt。


#include<bits/stdc++.h> 
using namespace std;
#define N 100005
struct node{
	int l,r;mutable int c;
	bool operator < (const node &x)const{return l<x.l;}
	node(int x,int y,int z){l=x;r=y;c=z;}
};
set<node> odt;
vector<int> G[N];
vector< pair<int,int> > qry[N];
pair<int,int> mn[N][20],mx[N][20];
int n,m,q,tot,a[N],fa[N],siz[N],dis[N],go[N][20],son[N],dfn[N],top[N],ans[N];
void dfs(int u,int d){
	go[u][0]=fa[u]=d;siz[u]=1;dis[u]=dis[d]+1;
	for(int i=1;(go[u][i]=go[go[u][i-1]][i-1]);i++);
	for(int v:G[u])if(v^d)
		dfs(v,u),siz[u]+=siz[v],son[u]=siz[son[u]]<siz[v]?v:son[u];
}
void dfs2(int u,int t){
	top[u]=t;dfn[u]=++tot;
	if(son[u])dfs2(son[u],t);
	for(int v:G[u])if((v^fa[u])&&(v^son[u]))
		dfs2(v,v);
}
int lca(int u,int v){
	if(dis[u]<dis[v])swap(u,v);
	for(int i=19;i>=0;i--)if(dis[go[u][i]]>=dis[v])u=go[u][i];
	if(u==v)return u;
	for(int i=19;i>=0;i--)if(go[u][i]!=go[v][i])u=go[u][i],v=go[v][i];
	return go[u][0];
}
int sum=0;
namespace bit{
	int tr[N];
	void add(int x,int y){sum+=y;++x;for(int i=x;i<=m+1;i+=(i&-i))tr[i]+=y;}
	int ask(int x){++x;int ans=0;for(int i=x;i;i-=(i&-i))ans+=tr[i];return ans;}
}
auto split(int x){
	if(x>n)return odt.end();
	auto it=--odt.upper_bound(node{x,0,0});
	if(it->l==x)return it;
	int l=it->l,r=it->r,c=it->c;
	odt.erase(it);odt.insert({l,x-1,c});
	return odt.insert(node{x,r,c}).first;
}
void assign(int l,int r,int c){
	auto itr=split(r+1),itl=split(l);
	for(auto it=itl;it!=itr;it++)
		bit::add(it->c,-(it->r)+(it->l)-1);
	bit::add(c,r-l+1);
	odt.erase(itl,itr);
	odt.insert(node{l,r,c});
}
int qrymn(int l,int r){
	int k=__lg(r-l+1);
	return min(mn[l][k],mn[r-(1<<k)+1][k]).second;
}
int qrymx(int l,int r){
	int k=__lg(r-l+1);
	return max(mx[l][k],mx[r-(1<<k)+1][k]).second;
}
int main(){
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),G[u].push_back(v),G[v].push_back(u);
	for(int i=1;i<=m;i++)scanf("%d",&a[i]);
	for(int i=1,l,r;i<=q;i++)scanf("%d%d",&l,&r),qry[r].push_back({l,i});
	dfs(1,0);dfs2(1,1);
	odt.insert({1,n,0});bit::add(0,n);
	for(int i=1;i<=m;i++)mn[i][0]={dfn[a[i]],a[i]},mx[i][0]={dfn[a[i]],a[i]};
	for(int k=1;k<=19;k++)for(int i=1;i+(1<<k)-1<=m;i++)
		mx[i][k]=max(mx[i][k-1],mx[i+(1<<k-1)][k-1]),
		mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]);
	for(int i=1;i<=m;i++){
		int u=a[i];
		while(u){
			assign(dfn[top[u]],dfn[u],i);
			u=fa[top[u]];
		}
		for(auto [l,id]:qry[i])ans[id]=n-bit::ask(l-1)-dis[lca(qrymn(l,i),qrymx(l,i))]+1;
	}
	for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
}
/*
5 10 1
1 2
2 3
2 4
2 5
4 3 4 4 1 3 1 3 2 4 
7 7

*/

标签:return,int,siz,odt,Day3,JOISC,go,Tourism,dis
From: https://www.cnblogs.com/xcyyyyyy/p/18351978

相关文章

  • (day31)leecode热题——多数元素
    描述给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊n/2⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。示例 1:输入:nums=[3,2,3]输出:3示例 2:输入:nums=[2,2,1,1,1,2,2]输出:2提示:n==......
  • day32【LeetCode力扣】541. 反转字符串 II
    day32【LeetCode力扣】541.反转字符串II1.题目描述给定一个字符串s和一个整数k,从字符串开头算起,每计数至2k个字符,就反转这2k字符中的前k个字符。如果剩余字符少于k个,则将剩余字符全部反转。如果剩余字符小于2k但大于或等于k个,则反转前k个字符,其余字符......
  • 从零开始的JAVAday29~day35
    后续语法if()语法若满足()中的语法,则执行后面的语句。循环for(a;b;c)和while(c)语法for(a;c;b)语法意思为在循环前进行a语句每次循环结束后进行b语法,若满足c语句则再次循环。whlie(c)循环若满足c条件则循环。......
  • DAY3 高精度算法(+,-,*,/)
    本文将要简单介绍acwing中的高精度算法,高精度指的就是有成百上千位的数进行运算,远远超出当前编程语言中的数据范围。\四个运算中的共同点都是数据位数较长(上千位),处理的方法都是将数据转化为字符串,再将字符串存进vector容器中,根据运算的基本特征进行处理首先介绍高精度加法:题......
  • 24暑假集训day3下午
    实现代码:intexgcd(inta,intb,int&x,int&y){ if(b==0){ x=1; y=0; returna; } intd=exgcd(b,a%b,x,y); intk=x; x=y; y=k-(a/b)*y; returnd;}intmain(){ inta=read(),b=read(); intx,y; intd=exgcd(a......
  • 24暑假集训day3上午
    进制转换一个\(m\)进制的数字\(\overline{a_0a_1\cdotsa_k}\)实际上是\(a_0m^k+a_1m^{k-1}+\cdots+a_k\)。\(10\)进制转\(m\)进制:每次除以\(m\)并取出余数。\(m\)进制转\(10\)进制:计算\(a_0m^k+a_1m^{k-}+\cdots+a_k\)。进制转换问题简述:将\(n\)进制数转换......
  • 代码随想录day32 || 509斐波那契数列 70爬楼梯 746使用最小花费爬楼梯
    509斐波那契数列力扣题目链接题目描述:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:F(0)=0,F(1) =1F(n)=F(n-1)+F(n-2),其中n>1给定 n ,请计算 F(n) 。代码1......
  • 代码随想录day31|| 56合并区间 738 递增数字
    56合并区间 力扣题目链接题目描述:以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i]=[starti,endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。示例1:输入:intervals=[[1,3],[2,6],[8,10],[1......
  • joisc2017 D3T1 长途巴士 题解
    joisc2017D3T1长途巴士题解这是学校ACM欢乐赛的题,赛时想到做法了,但是因为我各种唐诗没写出来翻了转化题面我们发现,只可以踢掉检查站前面一个连续段的接水人,并且不能踢掉司机,考虑画出对整个路程表示的线段上图几个小点是检查点,考虑在每个检查点之前踢掉一段的人,容易发......
  • 代码随想录Day3
    203.移除链表元素给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点。示例1:输入:head=[1,2,6,3,4,5,6],val=6输出:[1,2,3,4,5]示例2:输入:head=[],val=1输出:[]示例3:输入:head=[7,7,7,7],val=7......