QTREE6

来源:互联网 发布:病态矩阵特征值 编辑:程序博客网 时间:2024/06/04 01:17
对于一个节点,用树剖、线段树维护它为黑/ 白色时它所在联通块大小(仅限于以它为根的子树)。
由于是单点修改,可能受影响的只有其父亲、父亲的父亲、父亲的父亲的父亲、、、
因此把log个区间全部改掉就好了。
但是细节奇多无比。
还有,图中每一种情况都可能碰到根,请自行特判。
对于询问,只需不停跳爸爸,找到联通块内离它最远的颜色相同的祖先,单点查询即可。
昨晚调了半天,上BZOJ一交,发现自己T了。
然后上Vjudge上一交,半天都跑不出来,估计也T了,然后只能去睡觉了QAQ。
然而今早起来一看突然发现A了,删掉O2重交一发,发现跑得更快了?!
反正最后用了210秒死。
蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤
#include<cstdio>#include<cstring>#include<iostream>#include<vector>#include<algorithm>#include<set>#include<map>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define G getchar()#define LL long long#define pll pair<int,int>#define mkp make_pair#define X first#define Y secondconst int N=100005;int n;bool col[N];int he[N],ne[N<<1],to[N<<1],tot;int sz[N],dad[N],son[N],dfn[N],nfd[N],cnt,pre[N];LL sz0[N<<2],sz1[N<<2],lz0[N<<2],lz1[N<<2];int flg[N<<2];void read(int &x){char ch=getchar();while(ch<48||ch>57)ch=G;for(x=0;ch>=48&&ch<=57;ch=G)x=x*10+ch-48;}void add(int x,int y){to[++tot]=y;ne[tot]=he[x];he[x]=tot;}void DFS1(int x,int e){int y,i;sz[x]=1;for(i=he[x];i;i=ne[i])if(i!=e){pre[y=to[i]]=x;DFS1(y,i^1);if(sz[son[x]]<sz[y])son[x]=y;sz[x]+=sz[y];}}void DFS2(int x){int i,y;nfd[dfn[x]=++cnt]=x;dad[x]=son[pre[x]]==x?dad[pre[x]]:x;if(son[x])DFS2(son[x]);for(i=he[x];i;i=ne[i])if(!dfn[y=to[i]])DFS2(y);}void up0(int num){sz0[num]=sz0[num<<1]+sz0[num<<1|1];}void build0(int l,int r,int num){if(l==r){sz0[num]=sz[nfd[l]];return;}int mid=l+r>>1;build0(l,mid,num<<1);build0(mid+1,r,num<<1|1);up0(num);}void up1(int num){sz1[num]=sz1[num<<1]+sz1[num<<1|1];}void build1(int l,int r,int num){if(l==r){sz1[num]=1;return;}int mid=l+r>>1;build1(l,mid,num<<1);build1(mid+1,r,num<<1|1);up1(num);}void pd0(int x,int num){if(x>1){lz0[num<<1]+=lz0[num];lz0[num<<1|1]+=lz0[num];sz0[num<<1]+=lz0[num]*(x+1>>1);sz0[num<<1|1]+=lz0[num]*(x>>1);}lz0[num]=0;}LL query0(int x,int l,int r,int num){if(l==r)return sz0[num];int mid=l+r>>1;pd0(r-l+1,num);if(x<=mid)return query0(x,l,mid,num<<1);return query0(x,mid+1,r,num<<1|1);}void pd1(int x,int num){if(x>1){lz1[num<<1]+=lz1[num];lz1[num<<1|1]+=lz1[num];sz1[num<<1]+=lz1[num]*(x+1>>1);sz1[num<<1|1]+=lz1[num]*(x>>1);}lz1[num]=0;}LL query1(int x,int l,int r,int num){if(l==r)return sz1[num];int mid=l+r>>1;pd1(r-l+1,num);if(x<=mid)return query1(x,l,mid,num<<1);return query1(x,mid+1,r,num<<1|1);}void up2(int num){flg[num]=flg[num<<1]==flg[num<<1|1]?flg[num<<1]:2;}void modify2(int x,int l,int r,int num){if(l==r){flg[num]=col[nfd[l]];return;}int mid=l+r>>1;if(x<=mid)modify2(x,l,mid,num<<1);else modify2(x,mid+1,r,num<<1|1);up2(num);}int query2(int L,int R,int l,int r,int num){if(L<=l&&r<=R)return flg[num];int mid=l+r>>1;if(R<=mid)return query2(L,R,l,mid,num<<1);if(L>mid)return query2(L,R,mid+1,r,num<<1|1);int tmp=query2(L,R,l,mid,num<<1);return tmp==2||query2(L,R,mid+1,r,num<<1|1)!=tmp?2:tmp;}void modify0(int L,int R,LL x,int l,int r,int num){if(L<=l&&r<=R){lz0[num]+=x;sz0[num]+=(r-l+1)*x;return;}pd0(r-l+1,num);int mid=l+r>>1;if(L<=mid)modify0(L,R,x,l,mid,num<<1);if(R>mid)modify0(L,R,x,mid+1,r,num<<1|1);up0(num);}void modify1(int L,int R,LL x,int l,int r,int num){if(L<=l&&r<=R){lz1[num]+=x;sz1[num]+=(r-l+1)*x;return;}pd1(r-l+1,num);int mid=l+r>>1;if(L<=mid)modify1(L,R,x,l,mid,num<<1);if(R>mid)modify1(L,R,x,mid+1,r,num<<1|1);up1(num);}int main(){int i,Q,x,y,z,o,tmp,l,r,mid;LL gs0,gs1;bool co;read(n);tot=1;rep(i,2,n){read(x);read(y);add(x,y);add(y,x);}DFS1(1,0);DFS2(1);build0(1,n,1);build1(1,n,1);for(read(Q);Q--;){read(o);read(x);if(o){gs0=query0(dfn[x],1,n,1);gs1=query1(dfn[x],1,n,1);z=x;if(x>1){co=col[x=pre[x]];if(col[z]){modify0(dfn[x],dfn[x],gs0,1,n,1);modify1(dfn[x],dfn[x],-gs1,1,n,1);for(x=pre[x];x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==co;x=pre[y]){if(!co)modify0(dfn[y],dfn[x],gs0,1,n,1);else modify1(dfn[y],dfn[x],-gs1,1,n,1);}if(x){for(l=dfn[y]+1,r=dfn[x];l<=r;){mid=l+r>>1;if(query2(mid,dfn[x],1,n,1)==co)r=mid-1;else l=mid+1;}if(!co)modify0(r,dfn[x],gs0,1,n,1);else modify1(r,dfn[x],-gs1,1,n,1);}}else{modify0(dfn[x],dfn[x],-gs0,1,n,1);modify1(dfn[x],dfn[x],gs1,1,n,1);for(x=pre[x];x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==co;x=pre[y]){if(!co)modify0(dfn[y],dfn[x],-gs0,1,n,1);else modify1(dfn[y],dfn[x],gs1,1,n,1);}if(x){for(l=dfn[y]+1,r=dfn[x];l<=r;){mid=l+r>>1;if(query2(mid,dfn[x],1,n,1)==co)r=mid-1;else l=mid+1;}if(!co)modify0(r,dfn[x],-gs0,1,n,1);else modify1(r,dfn[x],gs1,1,n,1);}}}col[z]^=1;modify2(dfn[z],1,n,1);}else{if(col[x]){while(x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==1)x=pre[z=y];if(!x){printf("%d\n",query1(1,1,n,1));continue;}for(l=dfn[y]+1,r=dfn[x];l<=r;){mid=l+r>>1;if(query2(mid,dfn[x],1,n,1)==1)r=mid-1;else l=mid+1;}if(l>dfn[x])printf("%d\n",query1(dfn[z],1,n,1));else printf("%d\n",query1(l,1,n,1));}else{while(x&&!query2(dfn[y=dad[x]],dfn[x],1,n,1))x=pre[z=y];if(!x){printf("%d\n",query0(1,1,n,1));continue;}for(l=dfn[y]+1,r=dfn[x];l<=r;){mid=l+r>>1;if(!query2(mid,dfn[x],1,n,1))r=mid-1;else l=mid+1;}if(l>dfn[x])printf("%d\n",query0(dfn[z],1,n,1));else printf("%d\n",query0(l,1,n,1));}}}return 0;}


原创粉丝点击