bzoj千题计划275:bzoj4817: [Sdoi2017]树点涂色
http://www.lydsy.com/JudgeOnline/problem.php?id=4817
lct+线段树+dfs序
操作1:access
操作2:u到根的-v到根的-lca到根的*2+1
操作3:查询线段树区间最大值
1A,嘎嘎嘎
#include<cmath> #include<cstdio> #include<iostream> using namespace std; #define max(x,y) ((x)>(y) ? (x) : (y)) #define N 100001 int n; int front[N],to[N<<1],nxt[N<<1],tot; int id[N],dy[N],lst[N],tim; int dep[N]; int lim,F[N][17]; int mx[N<<2],tag[N<<2]; int root; int fa[N],ch[N][2]; bool rev[N]; int st[N],top; int ans; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void add(int u,int v) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; } void dfs(int x) { id[x]=++tim; dy[tim]=x; dep[x]=dep[fa[x]]+1; for(int i=front[x];i;i=nxt[i]) if(to[i]!=fa[x]) { F[to[i]][0]=fa[to[i]]=x; dfs(to[i]); } lst[x]=tim; } void build(int k,int l,int r) { if(l==r) { mx[k]=dep[dy[l]]; return; } int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); mx[k]=max(mx[k<<1],mx[k<<1|1]); } void down(int k) { mx[k<<1]+=tag[k]; tag[k<<1]+=tag[k]; mx[k<<1|1]+=tag[k]; tag[k<<1|1]+=tag[k]; tag[k]=0; } void change(int k,int l,int r,int opl,int opr,int w) { if(l>=opl && r<=opr) { mx[k]+=w; tag[k]+=w; return; } if(tag[k]) down(k); int mid=l+r>>1; if(opl<=mid) change(k<<1,l,mid,opl,opr,w); if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,w); mx[k]=max(mx[k<<1],mx[k<<1|1]); } void Change(int x,int w) { if(x==root) change(1,1,n,1,n,w); else if(id[x]>id[root] && id[x]<=lst[root]) change(1,1,n,id[x],lst[x],w); else { int t=root,c=dep[root]-dep[x]-1; for(int i=lim;i>=0;--i) if(c&(1<<i)) t=F[t][i]; if(id[t]>1) change(1,1,n,1,id[t]-1,w); if(lst[t]<n) change(1,1,n,lst[t]+1,n,w); } } int query1(int k,int l,int r,int pos) { if(l==r) return mx[k]; if(tag[k]) down(k); int mid=l+r>>1; if(pos<=mid) return query1(k<<1,l,mid,pos); return query1(k<<1|1,mid+1,r,pos); } void query2(int k,int l,int r,int opl,int opr) { if(l>=opl && r<=opr) { ans=max(ans,mx[k]); return; } if(tag[k]) down(k); int mid=l+r>>1; if(opl<=mid) query2(k<<1,l,mid,opl,opr); if(opr>mid) query2(k<<1|1,mid+1,r,opl,opr); } void push_down(int x) { if(rev[x]) { if(ch[x][0]) rev[ch[x][0]]^=1; if(ch[x][1]) rev[ch[x][1]]^=1; rev[x]^=1; } } bool is_root(int x) { return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } bool get_son(int x) { return ch[fa[x]][1]==x; } void rotate(int x) { int y=fa[x],z=fa[y]; bool k=ch[y][1]==x; if(!is_root(y)) ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][k^1]; ch[x][k^1]=y; fa[x]=z; fa[y]=x; fa[ch[y][k]]=y; } void splay(int x) { st[top=1]=x; for(int i=x;!is_root(i);i=fa[i]) st[++top]=fa[i]; for(int i=top;i;--i) push_down(st[i]); int y; while(!is_root(x)) { y=fa[x]; if(!is_root(y)) rotate(get_son(x)==get_son(y) ? x : y ); rotate(x); } } int find_root(int x) { push_down(x); while(ch[x][0]) { x=ch[x][0]; push_down(x); } return x; } void access(int x) { int t=0; while(x) { splay(x); if(ch[x][1]) Change(find_root(ch[x][1]),1); ch[x][1]=t; if(t) Change(find_root(t),-1); t=x; x=fa[x]; } } int get_lca(int u,int v) { if(dep[u]<dep[v]) std::swap(u,v); int d=dep[u]-dep[v]; for(int i=lim;i>=0;--i) if(d&(1<<i)) u=F[u][i]; if(u==v) return u; for(int i=lim;i>=0;--i) if(F[u][i]!=F[v][i]) u=F[u][i],v=F[v][i]; return F[u][0]; } int main() { int m; read(n); read(m); lim=log(n)/log(2); int u,v; for(int i=1;i<n;++i) { read(u); read(v); add(u,v); } dfs(1); for(int j=1;j<=lim;++j) for(int i=1;i<=n;++i) F[i][j]=F[F[i][j-1]][j-1]; build(1,1,n); root=1; int ty; int lca; while(m--) { read(ty); read(u); if(ty==1) access(u); else if(ty==2) { read(v); lca=get_lca(u,v); printf("%d\n",query1(1,1,n,id[u])+query1(1,1,n,id[v])-query1(1,1,n,id[lca])*2+1); } else { ans=0; query2(1,1,n,id[u],lst[u]); printf("%d\n",ans); } } }