CodeForces - 343D Water Tree(树链剖分+线段树)

题目链接:点击查看

题目大意:给出一棵树,然后给出m次操作,每次操作分为三种:

  1. 1 v:将v及其子树全部变为1
  2. 2 v:将v及其祖先全部变为0
  3. 3 v:查询点v的值

题目分析:树链剖分模板题,今下午刚做了一个比较难的,再回头看一下这个题,瞬间感觉简单好多了,为什么要挂着个题呢?为了提醒自己:

树链剖分后,线段树的建树、查询、访问用的都是全新的编号!!!!

这个样例也是坑人,样例中的5个点,剖分之后,还是对应着他们本身的编号,所以样例过了,第六个test WA了半天,还纳闷是dfs序写错了还是线段树写错了。。。真的服了自己了,上代码吧,这个题目用不到储存deep,就写的比较简单了

#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=5e5+100;

vectornode[N];

int son[N],fa[N],num[N];

void dfs1(int u,int f)
{
	son[u]=0;
	fa[u]=f;
	num[u]=1;
	for(int i=0;i>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}

void pushdown(int k)
{
	tree[k<<1].val=tree[k<<1|1].val=tree[k].lazy;
	tree[k<<1].lazy=tree[k<<1|1].lazy=tree[k].lazy;
	tree[k].lazy=-1;
}

void update(int k,int l,int r,int val)
{
	if(tree[k].rr)
		return;
	if(tree[k].l>=l&&tree[k].r<=r)
	{
		tree[k].val=val;
		tree[k].lazy=val;
		return;
	}
	if(tree[k].lazy!=-1)
		pushdown(k);
	update(k<<1,l,r,val);
	update(k<<1|1,l,r,val);
}

int query(int k,int pos)
{
	if(tree[k].l==tree[k].r)
		return tree[k].val;
	if(tree[k].lazy!=-1)
		pushdown(k);
	int mid=tree[k].l+tree[k].r>>1;
	if(mid>=pos)
		return query(k<<1,pos);
	else
		return query(k<<1|1,pos);
}

void update1(int x)
{
	update(1,id[x],id[x]+num[x]-1,1);
}

void update2(int x)
{
	while(top[x]!=1)
	{
		update(1,id[top[x]],id[x],0);
		x=fa[top[x]];
	}
	update(1,1,id[x],0);
}

int main()
{
//	freopen("input.txt","r",stdin);
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=1;i<=n;i++)
			node[i].clear();
		for(int i=1;i

 

你可能感兴趣的:(树链剖分,线段树)