_(:3 ⌒?)_ 调我半天,还是记录下吧。
用轻重链可解决此题。
用轻重链的方式给点重新编号后,建两棵线段树,一棵(sumTree)用于记录路径修改,另外一棵(markTree)用于记录邻边修改的点。
然后维护下两棵树即可。
注意,markTree修改时,要在sumTree上修改第一个点和最后一个点对应的重边,若修改的顶点为连接轻链的点,则sumTree对应边不修改。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> #define ll long long #define INF 0x3f3f3f3f #define BUG printf("hehe!~\n") #define lson(x) (x<<1) #define rson(x) (x<<1|1) #define y1 y123123 using namespace std; const int N=100010; int n; vector<int> G[N]; bool vis[N]; int size[N],fa[N],mxson[N]; int tot,num[N],top[N],pre[N],dep[N]; int y1,y2; struct Node { int l,r; int rev; int sum; }; void DFS(int x) { vis[x]=true; size[x]=1; int v; for(int i=0;i<G[x].size();++i) { v=G[x][i]; if(!vis[v]) { fa[v]=x; DFS(v); size[x]+=size[v]; if(size[v]>size[mxson[x]]) mxson[x]=v; } } vis[x]=false; } void make(int x,int depth,int tp) { ++tot; num[x]=tot; pre[tot]=x; top[x]=tp; dep[x]=depth; vis[x]=true; if(mxson[x]) { make(mxson[x],depth,tp); } int v; for(int i=0;i<G[x].size();++i) { v=G[x][i]; if(!vis[v]&&v!=mxson[x]) { make(v,depth+1,v); } } vis[x]=false; } struct MyTree { Node T[N<<2]; int _sum;//set 0 void buildtree(int u,int L,int R) { if(L==R) { T[u].l=L; T[u].r=R; T[u].sum=0; return; } int mid=(L+R)>>1; T[u].l=L,T[u].r=R,T[u].sum=0,T[u].rev=0; buildtree(lson(u),L,mid); buildtree(rson(u),mid+1,R); } void maintain(int u,int L,int R) { int lc=lson(u),rc=rson(u); if(R>L) { T[u].sum=T[lc].sum+T[rc].sum; } if(T[u].rev) T[u].sum=T[u].r-T[u].l+1-T[u].sum; } void rever(int u,int L,int R) { //if(y1>y2) return; //if(L>R) return; if(y1<=L&&y2>=R) { T[u].rev^=1; T[u].sum=T[u].r-T[u].l+1-T[u].sum; return; } else { int mid=(L+R)>>1; if(y1<=mid) rever(lson(u),L,mid); if(y2>mid) rever(rson(u),mid+1,R); } maintain(u,L,R); } void querysum(int u,int L,int R,int re) { if(y1<=L&&y2>=R) { if(re) _sum+=T[u].r-T[u].l+1-T[u].sum; else _sum+=T[u].sum; } else { int mid=(L+R)>>1; if(y1<=mid) querysum(lson(u),L,mid,re^T[u].rev); if(y2>mid) querysum(rson(u),mid+1,R,re^T[u].rev); } } }sumTree,markTree; void reverpath(int x,int y) { if(dep[x]>dep[y]) swap(x,y); while(dep[x]<dep[y]) { y1=num[top[y]],y2=num[y]; //cout<<x<<" "<<y<<" "<<y1<<" "<<y2<<endl; if(y1<=y2)sumTree.rever(1,1,n); y=fa[top[y]]; } while(top[x]!=top[y]) { y1=num[top[x]],y2=num[x]; if(y1<=y2) sumTree.rever(1,1,n); y1=num[top[y]],y2=num[y]; if(y1<=y2) sumTree.rever(1,1,n); x=fa[top[x]]; y=fa[top[y]]; } x=num[x],y=num[y]; if(x>y) swap(x,y); y1=x+1,y2=y; //cout<<x<<" "<<y<<" "<<y1<<" "<<y2<<endl; if(top[pre[y1]]==top[pre[y2]]&&y1<=y2) sumTree.rever(1,1,n); } void reveradj(int x,int y) { int ty,tx; if(dep[x]>dep[y]) swap(x,y); while(dep[x]<dep[y]) { y1=num[top[y]],y2=num[y]; if(y1<=y2) markTree.rever(1,1,n); ty=num[y]+1; if(top[pre[ty]]==top[y]) { y1=ty,y2=ty; sumTree.rever(1,1,n); } y=fa[top[y]]; } while(top[x]!=top[y]) { y1=num[top[y]],y2=num[y]; if(y1<=y2) markTree.rever(1,1,n); ty=num[y]+1; if(top[pre[ty]]==top[y]) { y1=ty,y2=ty; sumTree.rever(1,1,n); } y1=num[top[x]],y2=num[x]; if(y1<=y2) markTree.rever(1,1,n); tx=num[x]+1; if(top[pre[tx]]==top[x]) { y1=tx,y2=tx; sumTree.rever(1,1,n); } x=fa[top[x]]; y=fa[top[y]]; } //x=num[x],y=num[y]; if(num[x]>num[y]) swap(x,y); y1=num[x],y2=num[y]; if(y1<=y2) markTree.rever(1,1,n); //tx=num[x]-1; //if(top[pre[tx]]==top[x]) //sumTree.rever(1,tx,tx); if(x!=top[x]) { y1=num[x],y2=num[x]; sumTree.rever(1,1,n); } ty=num[y]+1; if(top[pre[ty]]==top[y]) { y1=ty,y2=ty; sumTree.rever(1,1,n); } } void query(int x,int y) { int ans=0; int lch,rch; if(dep[x]>dep[y]) swap(x,y); while(dep[x]<dep[y]) { y1=num[top[y]]+1,y2=num[y]; sumTree._sum=0; if(y1<=y2) sumTree.querysum(1,1,n,0); ans+=sumTree._sum; sumTree._sum=0; y1=num[top[y]],y2=num[top[y]]; sumTree.querysum(1,1,n,0); lch=sumTree._sum; markTree._sum=0; y1=num[top[y]],y2=num[top[y]]; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; y=fa[top[y]]; markTree._sum=0; y1=num[y],y2=num[y]; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; ans+=lch; } while(top[x]!=top[y]) {////////////////////////// y1=num[top[y]]+1,y2=num[y]; sumTree._sum=0; if(y1<=y2) sumTree.querysum(1,1,n,0); ans+=sumTree._sum; sumTree._sum=0; y1=num[top[y]],y2=num[top[y]]; sumTree.querysum(1,1,n,0); lch=sumTree._sum; markTree._sum=0; y1=num[top[y]],y2=num[top[y]]; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; y=fa[top[y]]; y1=num[y],y2=num[y]; markTree._sum=0; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; ans+=lch; y1=num[top[x]]+1,y2=num[x]; sumTree._sum=0; if(y1<=y2) sumTree.querysum(1,1,n,0); ans+=sumTree._sum; sumTree._sum=0; y1=num[top[x]],y2=num[top[x]]; sumTree.querysum(1,1,n,0); lch=sumTree._sum; markTree._sum=0; y1=num[top[x]],y2=num[top[x]]; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; x=fa[top[x]]; markTree._sum=0; y1=num[x],y2=num[x]; markTree.querysum(1,1,n,0); rch=markTree._sum; lch^=rch; ans+=lch; //x=fa[top[x]]; //y=fa[top[y]]; } if(num[x]>num[y]) swap(x,y); sumTree._sum=0; y1=num[x]+1,y2=num[y]; if(y1<=y2) sumTree.querysum(1,1,n,0); ans+=sumTree._sum; printf("%d\n",ans); } int main() { int _; int Q,c,a,b; cin>>_; while(_--) { scanf("%d",&n); tot=0; for(int i=0;i<=n;++i) G[i].clear(); for(int i=1;i<n;++i) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } fa[1]=-1; for(int i=1;i<=n;++i) mxson[i]=0; DFS(1); make(1,1,1); sumTree.buildtree(1,1,n); markTree.buildtree(1,1,n); scanf("%d",&Q); while(Q--) { scanf("%d%d%d",&c,&a,&b); //a=num[a];b=num[b]; if(1==c) reverpath(a,b); else if(2==c) reveradj(a,b); else query(a,b); } } }
HDU 4897 Little Devil I,布布扣,bubuko.com
原文:http://www.cnblogs.com/morimiya/p/3898118.html