zoukankan      html  css  js  c++  java
  • 睡觉困难综合征 树链剖分

    睡觉困难综合征

    LG传送门

    树剖好题。

    做这道题之前,请先做一做[NOI2014]起床困难综合症。记得我在我的树链剖分总结中的第一句话吗?这道题就是那道的上树带修版本。

    首先简单口胡一下起床困难综合症:只需要把每一位初始状态为零和为一的结果预处理出来,这个过程可以通过把(0)(inf)进行一遍题目中要求的操作来得到;然后从高位往低位贪心即可。

    上树带修之后就考虑用线段树维护上面预处理的结果。线段树维护四个值:

    ​ 从左往右(0)通过的结果:(f[0][0])

    ​ 从左往右(inf)通过的结果:(f[0][1])

    ​ 从右往左(0)通过的结果:(f[1][0])

    ​ 从右往左(inf)通过的结果:(f[1][1])

    当两个区间合并时,设左区间为(p),右区间为(q),合并后的区间为(k),以(k[0][0])的合并为例:若要使(k[0][0])的某一位为(1),要么(p[0][0])(q[0][1])同时为(1),要么(p[0][0])(0)(q[0][1])(1),那么(k[0][0])就是((p[0][0]&q[0][1])|(()$p[0][0])&q[0][0])$。这个结论请自己手玩~证明,对于其他信息的合并也可以使用同样的方式推导。

    在修改时,直接在线段树上更改某个点的值就好了。对于每一个询问,可以使用上面合并区间的方法合并重链上的信息,合并时注意谁是左区间谁右区间,从线段树上得到信息之后就按照区间上的做法一遍贪心得到答案。

    注意必须使用unsigned long long。代码不长(2.9K),实现起来细节很多。

    #include<cstdio>
    #include<cctype>
    #define R register
    #define I inline
    #define L unsigned long long
    using namespace std;
    const int S=100003,N=200003,M=400003;
    const L inf=-1;
    char buf[1000000],*p1,*p2;
    I char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,S,stdin),p1==p2)?EOF:*p1++;}
    I L rd(){
    	L f=0; R char c=gc();
    	while(c<48||c>57) c=gc();
    	while(c>47&&c<58) f=f*10+(c^48),c=gc();
    	return f;
    }
    int h[S],s[N],g[N],d[S],t[S],p[S],q[S],f[S],r[S],a[S],u[S],n,k,c;
    L b[S],v[S];
    struct E{
    	L a[2][2];
    	E(){a[0][0]=a[1][0]=0,a[0][1]=a[1][1]=inf;}
    	I L* operator[](int x){return a[x];}
    	I E operator+(E y){
    		E x=*this,o;
    		o[0][0]=(x[0][0]&y[0][1])|((~x[0][0])&y[0][0]);
    		o[0][1]=(x[0][1]&y[0][1])|((~x[0][1])&y[0][0]);
    		o[1][0]=(y[1][0]&x[1][1])|((~y[1][0])&x[1][0]);
    		o[1][1]=(y[1][1]&x[1][1])|((~y[1][1])&x[1][0]);
    		return o;
    	}
    }e[M];
    I void swp(L&x,L&y){x^=y,y^=x,x^=y;}
    I void add(int x,int y){s[++c]=h[x],h[x]=c,g[c]=y;}
    void dfs1(int x,int f){
    	p[x]=f,d[x]=d[f]+1,t[x]=1;
    	for(R int i=h[x],y,m=0;i;i=s[i])
    		if((y=g[i])^f){
    			dfs1(y,x),t[x]+=t[y];
    			if(t[y]>m)
    				q[x]=y,m=t[y];
    		}
    }
    void dfs2(int x,int t){
    	f[x]=++c,r[x]=t,u[c]=a[x],v[c]=b[x];
    	if(!q[x]) return;
    	dfs2(q[x],t);
    	for(R int i=h[x],y;i;i=s[i])
    		if((y=g[i])^p[x]&&y^q[x])
    			dfs2(y,y);
    }
    I void upd(int k,int x,L y){
    	if(x==1)
    		e[k][0][0]=e[k][1][0]=0,e[k][0][1]=e[k][1][1]=y;
    	if(x==2)
    		e[k][0][0]=e[k][1][0]=y,e[k][0][1]=e[k][1][1]=inf;
    	if(x==3)
    		e[k][0][0]=e[k][1][0]=y,e[k][0][1]=e[k][1][1]=inf^y;
    }
    I void psu(int k,int p,int q){e[k]=e[p]+e[q];}
    void bld(int k,int l,int r){
    	if(l==r){
    		upd(k,u[l],v[l]);
    		return ;
    	}
    	R int p=k<<1,q=p|1,m=l+r>>1;
    	bld(p,l,m),bld(q,m+1,r),psu(k,p,q);
    }
    void mdf(int k,int l,int r,int x,int y,L z){
    	if(l==r){
    		upd(k,y,z);
    		return ;
    	}
    	R int p=k<<1,q=p|1,m=l+r>>1;
    	if(x<=m)
    		mdf(p,l,m,x,y,z);
    	else
    		mdf(q,m+1,r,x,y,z);
    	psu(k,p,q);
    }
    E qry(int k,int l,int r,int x,int y){
    	if(x<=l&&r<=y)
    		return e[k];
    	R int p=k<<1,q=p|1,m=l+r>>1;
    	E o;
    	if(x<=m)
    		o=o+qry(p,l,m,x,y);
    	if(m<y)
    		o=o+qry(q,m+1,r,x,y);
    	return o;
    }
    L qry0(int x,int y,L z){
    	E t,u,v;
    	L o=0;
    	while(r[x]^r[y])
    		if(d[r[x]]>d[r[y]]){
    			t=qry(1,1,n,f[r[x]],f[x]),swp(t[0][0],t[1][0]),swp(t[0][1],t[1][1]);
    			u=u+t,x=p[r[x]];
    		}
    		else
    			v=qry(1,1,n,f[r[y]],f[y])+v,y=p[r[y]];
    	if(d[x]>d[y])
    		t=qry(1,1,n,f[y],f[x]),swp(t[0][0],t[1][0]),swp(t[0][1],t[1][1]),u=u+t+v;
    	else
    		u=u+qry(1,1,n,f[x],f[y])+v;
    	for(R int i=k-1;~i;--i)
    		if(u[0][0]>>i&1)
    			o+=1llu<<i;
    		else
    			if((u[0][1]>>i)&1&&1llu<<i<=z)
    				o+=1llu<<i,z-=1llu<<i;
    	return o;
    }
    int main(){
    	R int m,i,o,x,y;
    	L z;
    	n=rd(),m=rd(),k=rd();
    	for(i=1;i<=n;++i)
    		a[i]=rd(),b[i]=rd();
    	for(i=1;i<n;++i)
    		x=rd(),y=rd(),add(x,y),add(y,x);
    	c=0,dfs1(1,0),dfs2(1,1),bld(1,1,n);
    	for(i=1;i<=m;++i){
    		o=rd(),x=rd(),y=rd(),z=rd();
    		if(o==1)
    			printf("%llu
    ",qry0(x,y,z));
    		else
    			mdf(1,1,n,f[x],y,z);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    HTML5 Video/Audio播放本地文件
    jquery 美化弹出提示 漂亮的Dialog 对话框
    JavaScript中变量、作用域、内存问题
    利用nethogs查看哪些进程占用网络带宽
    Dell服务器硬件监控,使用omreport出现object not found 错误解决
    filebeat收集nginx的json格式日志
    利用logrotate切割nginx的access.log日志
    Linux下单机部署ELK日志收集、分析环境
    linux开启Rsyslog服务收集日志
    mysql占用磁盘IO过高的解决办法
  • 原文地址:https://www.cnblogs.com/cj-chd/p/10155103.html
Copyright © 2011-2022 走看看