BZOJ3862 Little Devil I 树链剖分

原文链接http://www.cnblogs.com/zhouzhendong/p/8081514.html


题目传送门 - BZOJ3862


题意概括

  一棵树,n个点,边权为黑或者白,支持3重操作:

  1.链上颜色翻转

  2.对于一条链,把有一个点在这条链上的边全部翻转颜色

  3.询问一条链上有多少黑色。


题解

  毒瘤题。

  对于1、3都是基础操作,很简单。

  主要是2.

  2的话,只需要打区间打标记,表示那些点的连向轻儿子的边全部翻转。然后修改的时候还有一堆特判(具体看代码)

  这题数据坑。

  有a==b的情况,小心了。我被坑了一个下午。

  我是怎么找到这个数据的呢?

  if (a==b) OLE();

void OLE(){
	int a[100];
	for (int i=23333;;i=i*i)
		printf("233");
}

  


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
bool isd(char ch){return '0'<=ch&&ch<='9';}
int read(){
	int x=0;
	char ch=getchar();
	while (!isd(ch))
		ch=getchar();
	while (isd(ch))
		x=(x<<1)+(x<<3)+ch-48,ch=getchar();
	return x;
}
const int N=100005;
struct Gragh{
	int cnt,y[N*2],nxt[N*2],fst[N];
	void clear(){
		cnt=0;
		memset(fst,0,sizeof fst);
	}
	void add(int a,int b){
		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
	}
}g;
int T,n,q,cnp;
int size[N],fa[N],depth[N],son[N],p[N],ap[N],top[N];
void Get_Gen_Info(int rt,int pre,int d){
	size[rt]=1,son[rt]=-1,fa[rt]=pre,depth[rt]=d;
	for (int i=g.fst[rt];i;i=g.nxt[i])
		if (g.y[i]!=pre){
			int s=g.y[i];
			Get_Gen_Info(s,rt,d+1);
			size[rt]+=size[s];
			if (son[rt]==-1||size[s]>size[son[rt]])
				son[rt]=s;
		}
}
void Get_Top(int rt,int tp){
	top[rt]=tp;
	ap[p[rt]=++cnp]=rt;
	if (!~son[rt])
		return;
	Get_Top(son[rt],tp);
	for (int i=g.fst[rt];i;i=g.nxt[i]){
		int s=g.y[i];
		if (s!=fa[rt]&&s!=son[rt])
			Get_Top(s,s);
	}
}
const int S=N*4;
struct Tree{
	int sum,size,r,sr;
}t[S];
void build(int rt,int L,int R){
	t[rt].size=R-L+1,t[rt].sum=t[rt].r=t[rt].sr=0;
	if (L==R)
		return;
	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
	build(ls,L,mid);
	build(rs,mid+1,R);
}
void pushup(int rt){
	int ls=rt<<1,rs=ls|1;
	t[rt].sum=t[ls].sum+t[rs].sum;
}
void pushdown(int rt){
	int ls=rt<<1,rs=ls|1;
	int &sr=t[rt].sr,&r=t[rt].r;
	if (sr)
		t[ls].sr^=1,t[rs].sr^=1,sr=0;
	if (r){
		t[ls].r^=1,t[ls].sum=t[ls].size-t[ls].sum;
		t[rs].r^=1,t[rs].sum=t[rs].size-t[rs].sum;
		r=0;
	}
}
void update(int rt,int L,int R,int xL,int xR,int op){
	if (R<xL||L>xR)
		return;
	if (xL<=L&&R<=xR){
		if (op==1){
			t[rt].sum=t[rt].size-t[rt].sum;
			t[rt].r^=1;
		}
		else
			t[rt].sr^=1;
		return;
	}
	pushdown(rt);
	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
	update(ls,L,mid,xL,xR,op);
	update(rs,mid+1,R,xL,xR,op);
	pushup(rt);
}
int query(int rt,int L,int R,int xL,int xR){
	if (R<xL||L>xR)
		return 0;
	if (xL<=L&&R<=xR)
		return t[rt].sum;
	pushdown(rt);
	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
	return query(ls,L,mid,xL,xR)+query(rs,mid+1,R,xL,xR);
}
int asksr(int rt,int L,int R,int pos){
	if (L==R)
		return t[rt].sr;
	pushdown(rt);
	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
	if (pos<=mid)
		return asksr(ls,L,mid,pos);
	else
		return asksr(rs,mid+1,R,pos);
}
void Tupdate(int a,int b,int op){
	if (a==b)
		return;
	int f1=top[a],f2=top[b];
	while (f1!=f2){
		if (depth[f1]<depth[f2])
			swap(f1,f2),swap(a,b);
		update(1,1,n,p[f1],p[a],op);
		if (op==2){
			update(1,1,n,p[f1],p[f1],1);
			if (~son[a])
				update(1,1,n,p[son[a]],p[son[a]],1);
		}
		a=fa[f1],f1=top[a];
	}
	if (depth[a]>depth[b])
		swap(a,b);
	if (op==2){
		update(1,1,n,p[a],p[b],2);
		update(1,1,n,p[a],p[a],1);
		if (~son[b])
			update(1,1,n,p[son[b]],p[son[b]],1);
	}
	else if (a!=b)
		update(1,1,n,p[son[a]],p[b],op);
}
int Tquery(int a,int b){
	int f1=top[a],f2=top[b],ans=0;
	while (f1!=f2){
		if (depth[f1]<depth[f2])
			swap(f1,f2),swap(a,b);
		if (f1!=a)
			ans+=query(1,1,n,p[son[f1]],p[a]);
		ans+=query(1,1,n,p[f1],p[f1])^asksr(1,1,n,p[fa[f1]]);
		a=fa[f1],f1=top[a];
	}
	if (depth[a]>depth[b])
		swap(a,b);
	if (a!=b)
		ans+=query(1,1,n,p[son[a]],p[b]);
	return ans;
}
int main(){
	T=read();
	while (T--){
		n=read();
		g.clear();
		for (int i=1,a,b;i<n;i++){
			a=read(),b=read();
			g.add(a,b),g.add(b,a);
		}
		cnp=0;
		Get_Gen_Info(1,0,0);
		Get_Top(1,1);
		build(1,1,n);
		q=read();
		while (q--){
			int op,a,b;
			op=read(),a=read(),b=read();
			if (a==b){
				if (op==3)
					puts("0");
				if (op==2){
					update(1,1,n,p[a],p[a],2);
					if (~son[a])
						update(1,1,n,p[son[a]],p[son[a]],1);
					if (fa[a])
						update(1,1,n,p[a],p[a],1);
				}
				continue;
			}
			if (op<3)
				Tupdate(a,b,op);
			if (op==3)
				printf("%d
",Tquery(a,b));
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3862.html