• 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;
    }
    

      

  • 相关阅读:
    javaScript真值和假值以及相等操作符
    javaScript操作符
    javascript变量作用域
    javaScript变量
    Linux命令学习之路——档案拷贝:cp
    Linux命令学习之路——变更文档拥有者:chown
    Linux命令学习之路——文档权限管理:chmod
    Linux命令学习之路——变更工作目录:cd
    关于Scrum团队的理解
    关于MATHAPP的测试
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3862.html
Copyright © 2020-2023  润新知