首页 > 其他分享 >[SDOI2017] 树点涂色

[SDOI2017] 树点涂色

时间:2023-12-19 10:34:15浏览次数:37  
标签:测试点 树点 tp leq int ls 涂色 SDOI2017 itr

[SDOI2017] 树点涂色

题目描述

Bob 有一棵 \(n\) 个点的有根树,其中 \(1\) 号点是根节点。Bob 在每个点上涂了颜色,并且每个点上的颜色不同。

定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。

Bob可能会进行这几种操作:

  • 1 x 表示把点 \(x\) 到根节点的路径上所有的点染上一种没有用过的新颜色。

  • 2 x y 求 \(x\) 到 \(y\) 的路径的权值。

  • 3 x 在以 \(x\) 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

Bob一共会进行 \(m\) 次操作

输入格式

第一行两个数 \(n,m\)。

接下来 \(n-1\) 行,每行两个数 \(a,b\),表示 \(a\) 与 \(b\) 之间有一条边。

接下来 \(m\) 行,表示操作,格式见题目描述

输出格式

每当出现 \(2,3\) 操作,输出一行。

如果是 \(2\) 操作,输出一个数表示路径的权值

如果是 \(3\) 操作,输出一个数表示权值的最大值

样例 #1

样例输入 #1

5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5

样例输出 #1

3
4
2
2

提示

共 \(10\) 个测试点。

测试点 \(1\),\(1\leq n,m\leq1000\);

测试点 \(2,3\),没有 \(2\) 操作;

测试点 \(4,5\),没有 \(3\) 操作;

测试点 \(6\),树的生成方式是,对于 \(i(2\leq i \leq n)\),在 \(1 \sim i-1\) 中随机选一个点作为 \(i\) 的父节点;

测试点 \(7\),\(1\leq n,m\leq 5\times 10^4\);

测试点 \(8\),\(1\leq n \leq 5 \times 10^4\);

测试点9,10,无特殊限制

对所有数据,\(1\leq n \leq 10^5\),\(1\leq m \leq 10^5\)。

这题和 LCT 关系很大。

先说比较淳朴的树剖做法。先树剖,然后你考虑用 ODT 去维护每一段的信息。询问的时候也就是要求用线段树维护一个点的所有祖先中有多少个点他和他的父亲颜色不一样。询问2差分回答,询问3就是拍成 dfs 序后子树询问最大值。

现在只关注某一条重链。那么每次覆盖是一个前缀覆盖,那么颜色段数量每次最多增加一个,而覆盖的时候也是只会减不会增。所以对于一条重链他的均摊修改次数时 \(O(n)\) 的,对于所有重链来说颜色段均摊修改次数就是 \(O(nlogn)\) 的。那么就是说均摊有 \(O(nlog n)\) 次修改,使得一个点和他的父亲颜色不一样。如果我们可以知道用 ODT 找到每次改变的点这样的修改,然后用线段树暴力改,总复杂度 \(O(nlog^2n)\)

但是这个问题和 LCT 有什么关系呢?你会发现 操作 1 和 LCT 的 access 几乎一样。而 access 的复杂度证明就是和上面差不多,但是他用自平衡的 splay 替换了我们用的 set。如果你用 LCT 的话,这道题就是每次 access 后找到父亲和儿子不一样的地方,然后用线段树子树加。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,tp[N],fa[N],tr[N<<2],tg[N<<2],dep[N],in[N],sz[N],son[N],idx,ss[N],t[N],dfn[N];
set<pair<int,int> >s[N];
vector<int>g[N];
void pushdown(int o)
{
	tr[o<<1]+=tg[o],tr[o<<1|1]+=tg[o];
	tg[o<<1]+=tg[o],tg[o<<1|1]+=tg[o];
	tg[o]=0;
}
void upd(int o,int l,int r,int x,int y,int z)
{
	if(x<=l&&r<=y)
	{
		tg[o]+=z,tr[o]+=z;
		return;
	}
	pushdown(o);
	int md=l+r>>1;
	if(md>=x)
		upd(o<<1,l,md,x,y,z);
	if(md<y)
		upd(o<<1|1,md+1,r,x,y,z);
	tr[o]=max(tr[o<<1],tr[o<<1|1]);
}
int ask(int o,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
		return tr[o];
	pushdown(o);
	int md=l+r>>1,ret=0;
	if(md>=x)
		ret=ask(o<<1,l,md,x,y);
	if(md<y)
		ret=max(ret,ask(o<<1|1,md+1,r,x,y));
	return ret;
}
void dfs(int x,int y)
{
	fa[x]=y,sz[x]=1,dep[x]=dep[y]+1;
	for(int v:g[x])
	{
		if(v^y)
		{
			dfs(v,x);
			sz[x]+=sz[v];
			if(sz[v]>sz[son[x]])
				son[x]=v;
		}
	}
}
void sou(int x,int y,int d)
{
	tp[x]=d;
	in[x]=++idx,ss[idx]=sz[x];
	dfn[idx]=x;
	s[d].insert(make_pair(idx,idx));
	if(son[x])
		sou(son[x],x,d);
	for(int v:g[x])
		if(v^y&&v^son[x])
			sou(v,x,v);
}
int lca(int x,int y)
{
	while(tp[x]^tp[y])
	{
		if(dep[tp[x]]<dep[tp[y]])
			swap(x,y);
		x=fa[tp[x]];
	}
	if(in[x]<in[y])
		return x;
	return y;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		g[u].push_back(v),g[v].push_back(u);
	}
	dfs(1,0);
	sou(1,0,1);
	for(int i=1;i<=n;i++)
		upd(1,1,n,in[i],in[i],dep[i]-1);
	for(int i=1,op,x,y,z;i<=m;i++)
	{
		scanf("%d%d",&op,&x);
		if(op==1)
		{
			int ls=0;
			while(x)
			{
				auto itr=--s[tp[x]].upper_bound(make_pair(in[x],100000000));
				for(auto it=s[tp[x]].begin();it!=itr;it++)
				{
					if(it!=s[tp[x]].begin())
						upd(1,1,n,it->first,it->first+ss[it->first]-1,-1);
					if(t[it->second])
						upd(1,1,n,t[it->second],t[it->second]+ss[t[it->second]]-1,1),t[it->second]=0;
				}
				if(itr->second^in[x])
				{
					upd(1,1,n,in[x]+1,in[x]+ss[in[x]+1],1);
					s[tp[x]].insert(make_pair(in[x]+1,itr->second));
				}
				else
				{
					if(ls!=t[in[x]]&&t[in[x]])
						upd(1,1,n,t[in[x]],t[in[x]]+ss[t[in[x]]]-1,1);
				}
				if(itr!=s[tp[x]].begin())
					upd(1,1,n,itr->first,itr->first+ss[itr->first]-1,-1);
				s[tp[x]].erase(s[tp[x]].begin(),itr);
				s[tp[x]].erase(itr);
				s[tp[x]].insert(make_pair(in[tp[x]],in[x]));
				if(t[in[x]]^ls&&ls)
					upd(1,1,n,ls,ls+ss[ls]-1,-1);
				t[in[x]]=ls;
				ls=in[tp[x]];
				x=fa[tp[x]];
			}
		}
		else if(op==2)
		{
			scanf("%d",&y),z=lca(x,y);
			printf("%d\n",1+ask(1,1,n,in[x],in[x])+ask(1,1,n,in[y],in[y])-2*ask(1,1,n,in[z],in[z]));
		}
		else
			printf("%d\n",1+ask(1,1,n,in[x],in[x]+sz[x]-1));
	}
}

标签:测试点,树点,tp,leq,int,ls,涂色,SDOI2017,itr
From: https://www.cnblogs.com/mekoszc/p/17913128.html

相关文章

  • 涂色
    首先是一种对于这个问题的新的建树方法然后注意lazy标记最开始要初始化为0,不能为1或2,为0的时候表示自己当前的操作已经全部传递给子节点了注意lazy表示的是自己已经完成修改,但是子节点还没有修改,无论是这道题目还是普通的区间加减,我们在递归到一个节点的时候,他的所有祖先结点......
  • P4170 [CQOI2007] 涂色(天赋哥不要点进来)
    前言翻遍洛谷题解,看到大家都在套模板,却很少有人讲出为什么,使我十分崇拜天赋哥。原题链接关于这题的一些事实性证据事实1.来自事实2.来自事实3.来自事实4.来自整理上述事实1.每一次”最短“最优涂色,要么在其他颜色的基础上涂,这称之为融入一个整体;要么另辟蹊径单独......
  • luogu P3783 [SDOI2017] 天才黑客
    题面传送门为啥大家都写两个log的线段树优化建边啊,神秘,这1log做法好想又好写捏。首先显然是可以把边看成点的,这样会变成\(O(m)\)个点和\(O(m^2)\)条边,寄。但是还没有完全寄掉,我们发现,对于原图的每个点,对于第一个跑到这个点的边暴力转移,剩下的边转移只有一个子树,否则会......
  • 全局平衡二叉树学习笔记 && [SDOI2017]切树游戏解题报告
    首先,任何一个卡树剖的出题人都很没有素质前言2023年8月22日,XDFnoip模拟赛场上,神犇liuhangxin自己发明了矩阵乘法维护FWT,可是出成绩的时候发现本题挂了30分。2023年9月22日,菜鸡cool_milo看到了liuhangxin的题解,但是由于太菜,并没有看懂。2023年10月22日,菜......
  • Q7.4.1.2. 奇怪的方格涂色 题解
    原题链接首先想到暴力网络流:考虑最小割,\(S\)表示染黑色,\(T\)表示染白色。每个格子\(i\),连\((S,i,b_i)\),\((i,T,w_i)\)。怎么处理“奇怪的方格”?连\((i,i^\prime,p_i)\)和\((i^\prime,j,+\infty)\)。表示如果\(i\)归属于\(S\)(染黑色),那么就只能忍受奇怪所带来的\(p_i\)......
  • P3784 [SDOI2017] 遗忘的集合
    传送门description对于一个元素都\(\leqn\)的正整数集合\(S\)(不含相同元素),\(f(i)\)表示使用集合\(S\)里的数加和为\(i\)的方案数,每个元素可以被使用多次,两个方案不同当且仅当存在一个元素在两种方案中使用次数不同。现给定\(n\)和\(f(i),1\leqi\leqn\)。求出集......
  • 解题报告 P3704 [SDOI2017] 数字表格
    P3704[SDOI2017]数字表格经典莫反。题目要求:\[\prod_{i=1}^n\prod_{j=1}^mfib(\gcd(i,j))\]不妨令\(n<m\)。套路地,我们设\(\gcd(i,j)=d\),然后枚举\(d\):\[\begin{aligned}&\quad\prod_{d=1}^n\prod_{i=1}^n\prod_{j=1}^mfib(d)^{[\gcd(i,j)==d]}\\&=\pr......
  • P3780 [SDOI2017] 苹果树 题解
    DescriptionP3780[SDOI2017]苹果树给定一棵\(n\)个点的树,每个点有若干个价值相同的苹果,儿子能摘至少一个仅当父亲被摘至少一个。给定\(k\),设\(h\)为你摘的苹果的最大深度,你做多能摘\(k+h\)个,求最大价值。对于所有数据,\(1\len\le5\times10^4\),\(1\lek\le5\time......
  • [刷题笔记] CF1132F Clear the String & [CQOI2007] 涂色
    Problem1Problem2双倍经验qwqDescription初始时数组为空,每次可以选择一个区间\(l-r\)将其赋为同一个值,赋的值可以覆盖,给定数组的目标形式,求至少经过多少次操作使得空数组变成目标形式。Solution我们发现每次选择一个区间,大区间包含小区间,小区间可以推到大区间。因此考虑区间......
  • [SDOI2017] 数字表格
    传送门跟YY的gcd如出一辙,得到一个显然的柿子\[\prod_{k}F_{k}^{z}\]\[z=\sum_{d}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor\]那么我们设T=kd,\[\prod_{T}\prod_{k|T}F_{k}^x\]\[x=\mu(\frac{T}{k})\lfloor\frac{n}{T}\rfloor\lfl......