bzoj 4817: [Sdoi2017]树点涂色【树链剖分+LCT】
2018-01-08 20:25
375 查看
非常妙的一道题。
首先对于操作一“把点x到根节点的路径上所有的点染上一种没有用过的新颜色”,长得是不是有点像LCT中的access操作?进而发现,如果把同一颜色的点连起来作为LCT中的重边的话,那么询问二就相当于问路径上的虚边有多少。
然后第二、三个操作是可以用树剖在线段树上维护的。
设每个点的权值\( val \)为这个点到根的路径上颜色个数,也就是虚边个数。那么考虑access操作的影响,对于他断开的重边,所在子树加一,对于他连上的重边,所在子树减一。直接在access过程中处理即可。
对于操作一,直接access;
对于操作二,\( ans=val[x]+val[y]-2*val[lca(x,y)]+1 \);
对于操作三,用线段树维护区间最大值,直接查询即可。
#include<iostream> #include<cstdio> using namespace std; const int N=300005; int n,m,h ,cnt,si ,fa ,de ,hs ,fr ,id ,tmp,rl ; struct qwe { int ne,to; }e[N<<1]; struct xianduanshu { int l,r,mx,lz; }q[N<<2]; struct pinghengshu { int f,c[2]; }t ; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(f==-1) f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; h[u]=cnt; } void dfs1(int u,int fat) { fa[u]=fat; de[u]=de[fat]+1; si[u]=1; for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fat) { dfs1(e[i].to,u); si[u]+=si[e[i].to]; if(si[e[i].to]>si[hs[u]]) hs[u]=e[i].to; } } void dfs2(int u,int top) { fr[u]=top; id[u]=++tmp; rl[tmp]=u; if(!hs[u]) return; dfs2(hs[u],top); for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fa[u]&&e[i].to!=hs[u]) dfs2(e[i].to,e[i].to); } int lca(int u,int v) { for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);//cout<<u<<" "<<v<<" "<<" ";if(de[u]>de[v])cout<<v;else cout<<u;cout<<endl; return de[u]>de[v]?v:u; } void build(int ro,int l,int r) { q[ro].l=l,q[ro].r=r; if(l==r) { q[ro].mx=de[rl[l]]; // cout<<rl[l]<<" "<<q[ro].mx<<endl; return; } int mid=(l+r)>>1; build(ro<<1,l,mid); build(ro<<1|1,mid+1,r); q[ro].mx=max(q[ro<<1].mx,q[ro<<1|1].mx); } void pd(int ro) { q[ro<<1].mx+=q[ro].lz; q[ro<<1].lz+=q[ro].lz; q[ro<<1|1].mx+=q[ro].lz; q[ro<<1|1].lz+=q[ro].lz; q[ro].lz=0; } void update(int ro,int l,int r,int v) {//cout<<l<<" "<<r<<" "<<v<<endl; if(q[ro].l==l&&q[ro].r==r) { q[ro].mx+=v; q[ro].lz+=v; return; } if(q[ro].lz) pd(ro); int mid=(q[ro].l+q[ro].r)>>1; if(r<=mid) update(ro<<1,l,r,v); else if(l>mid) update(ro<<1|1,l,r,v); else { update(ro<<1,l,mid,v); update(ro<<1|1,mid+1,r,v); } q[ro].mx=max(q[ro<<1].mx,q[ro<<1|1].mx); } int ques(int ro,int l,int r) { if(q[ro].l==l&&q[ro].r==r) return q[ro].mx; if(q[ro].lz) pd(ro); int mid=(q[ro].l+q[ro].r)>>1; if(r<=mid) return ques(ro<<1,l,r); else if(l>mid) return ques(ro<<1|1,l,r); else return max(ques(ro<<1,l,mid),ques(ro<<1|1,mid+1,r)); } bool srt(int x) { return t[t[x].f].c[0]!=x&&t[t[x].f].c[1]!=x; } void zhuan(int x) { int l,r,y=t[x].f,z=t[y].f; if(t[y].c[0]==x) l=0; else l=1; r=l^1; if(!srt(y)) { if(t[z].c[0]==y) t[z].c[0]=x; else t[z].c[1]=x; } t[x].f=z;t[y].f=x; t[t[x].c[r]].f=y; t[y].c[l]=t[x].c[r]; t[x].c[r]=y; } void splay(int x) { while(!srt(x)) { int y=t[x].f,z=t[y].f; if(!srt(y)) { if((t[y].c[0]==x)^(t[z].c[0]==y)) zhuan(x); else zhuan(y); } zhuan(x); } } void acc(int x) { for(int i=0;x;i=x,x=t[x].f) { splay(x); if(t[x].c[1]) { int y=t[x].c[1]; while(t[y].c[0]) y=t[y].c[0]; update(1,id[y],id[y]+si[y]-1,1); } t[x].c[1]=i; if(t[x].c[1]) { int y=t[x].c[1]; while(t[y].c[0]) y=t[y].c[0]; update(1,id[y],id[y]+si[y]-1,-1); } } } int main() { n=read(),m=read(); for(int i=1;i<n;i++) { int x=read(),y=read(); add(x,y);add(y,x); } dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i=2;i<=n;i++) t[i].f=fa[i]; while(m--) { int o=read(); if(o==1) { int x=read(); acc(x); } else if(o==2) { int x=read(),y=read(),lc=lca(x,y); printf("%d\n",ques(1,id[x],id[x])+ques(1,id[y],id[y])-2*ques(1,id[lc],id[lc])+1); // printf("%d %d %d %d\n",ques(1,id[x],id[x]),ques(1,id[y],id[y]),ques(1,id[lc],id[lc]),ques(1,id[fa[lc]],id[fa[lc]])); } else { int x=read(); printf("%d\n",ques(1,id[x],id[x]+si[x]-1)); } } return 0; }
相关文章推荐
- bzoj4817[Sdoi2017]树点涂色
- BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
- bzoj 4817: [Sdoi2017]树点涂色
- bzoj 4817: [Sdoi2017]树点涂色
- bzoj4817: [Sdoi2017]树点涂色
- AC日记——[SDOI2017]树点涂色 bzoj 4817
- bzoj 4817: [Sdoi2017]树点涂色 link cut tree+线段树+树链剖分
- BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)
- [LCT] BZOJ4817.[Sdoi2017]树点涂色
- [BZOJ]4817: [Sdoi2017]树点涂色
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
- BZOJ 4817: [Sdoi2017]树点涂色
- bzoj 4817: [Sdoi2017]树点涂色 LCT+树链剖分+线段树
- [BZOJ4817][SDOI2017]树点涂色(DFS序+LCA+树剖+LCT)
- bzoj4817 [Sdoi2017]树点涂色
- bzoj千题计划275:bzoj4817: [Sdoi2017]树点涂色
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
- BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树
- 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)