[LCT] BZOJ 4817 [Sdoi2017]树点涂色

来源:互联网 发布:手机淘宝登录名怎么改 编辑:程序博客网 时间:2024/06/05 08:51

怎么萎事啊 sdoi怎么有这么多原题
看着这么眼熟
就是我们发现这个染色就是LCT上一个access的过程
而一个点到根路径的颜色数就是到根虚边数加1
这个我们可以access的时候顺便在线段树上子树修改下
而两个点之间的路径颜色数就是加一加再减去lca的两倍然后再加1 那个加1是指lca所属的颜色
子树最大值 直接线段树上查咯

#include<cstdio>#include<cstdlib>#include<stack>#include<algorithm>using namespace std;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;const int K=18;struct edge{  int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){  G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}#define V G[p].vint size[N],depth[N],fat[N][K];int pre[N],clk,back[N];inline void dfs(int u,int fa){  fat[u][0]=fa; depth[u]=depth[fa]+1;  size[u]=1; pre[u]=++clk; back[clk]=u;  for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];  for (int p=head[u];p;p=G[p].next)    if (V!=fa)      dfs(V,u),size[u]+=size[V];}inline int LCA(int u,int v){  if (depth[u]<depth[v]) swap(u,v);  for (int k=K-1;~k;k--)    if ((depth[u]-depth[v])>>k&1)      u=fat[u][k];  if (u==v) return u;  for (int k=K-1;~k;k--)    if (fat[u][k]!=fat[v][k])      u=fat[u][k],v=fat[v][k];  return fat[u][0];}struct SEG{  int T[N<<2],F[N<<2];  inline void Build(int x,int l,int r){    if (l==r){      T[x]=depth[back[l]]-1; return;    }    int mid=(l+r)>>1;    Build(x<<1,l,mid);    Build(x<<1|1,mid+1,r);    T[x]=max(T[x<<1],T[x<<1|1]);  }  inline void mark(int x,int t){    F[x]+=t; T[x]+=t;  }  inline void Add(int x,int l,int r,int ql,int qr,int t){    if (ql<=l && r<=qr){      mark(x,t); return;    }    if (F[x]) mark(x<<1,F[x]),mark(x<<1|1,F[x]),F[x]=0;    int mid=(l+r)>>1;    if (ql<=mid) Add(x<<1,l,mid,ql,qr,t);    if (qr>mid) Add(x<<1|1,mid+1,r,ql,qr,t);    T[x]=max(T[x<<1],T[x<<1|1]);  }  inline int Query(int x,int l,int r,int ql,int qr){    if (ql<=l && r<=qr) return T[x];    if (F[x]) mark(x<<1,F[x]),mark(x<<1|1,F[x]),F[x]=0;    int mid=(l+r)>>1,ret=-1<<30;    if (ql<=mid) ret=max(ret,Query(x<<1,l,mid,ql,qr));    if (qr>mid) ret=max(ret,Query(x<<1|1,mid+1,r,ql,qr));    return ret;  }}Seg;int n;inline void Add(int x,int t){  Seg.Add(1,1,n,pre[x],pre[x]+size[x]-1,t);}inline int Query(int x){  return Seg.Query(1,1,n,pre[x],pre[x])+1;}struct node{  node *ch[2],*f;  bool dir(){ return f->ch[1]==this; }  bool isr(){ return !f || (f->ch[0]!=this && f->ch[1]!=this); }  void setc(node *c,int d){ ch[d]=c; if (c) c->f=this; }  //void push(){ }  //void upd(){ }}pool[N];inline void rot(node *x){  node *p=x->f; bool d=x->dir();  if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;  p->setc(x->ch[d^1],d),x->setc(p,d^1);// p->upd();}//stack<node*> sta;inline void splay(node *x){  //node *q=x; while (!q->isr()) sta.push(q),q=q->f; sta.push(q);  //while (!sta.empty()) sta.top()->push(),sta.pop();  while (!x->isr())    if (x->f->isr()) rot(x);    else if (x->dir()==x->f->dir()) rot(x->f),rot(x);    else rot(x),rot(x);  //x->upd();}inline node *frt(node *x){  splay(x); for (;/*x->push(),*/x->ch[0];x=x->ch[0]); return x;}inline void expose(node *x){  for (node *q=NULL;x;q=x,x=x->f){    splay(x);    node *ch=x->ch[1]; x->ch[1]=NULL;    if (ch) Add(frt(ch)-pool,1);    if (q) Add(frt(q)-pool,-1);    x->ch[1]=q;    //x->upd();  }}int main(){  int Q,order,iu,iv;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(Q);  for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);  dfs(1,0);  Seg.Build(1,1,n);  for (int i=2;i<=n;i++) pool[i].f=pool+fat[i][0];  while (Q--){    read(order); read(iu);    if (order==1){      expose(pool+iu);    }else if (order==2){      read(iv); int lca=LCA(iu,iv);      printf("%d\n",Query(iu)+Query(iv)-2*Query(lca)+1);    }else{      printf("%d\n",Seg.Query(1,1,n,pre[iu],pre[iu]+size[iu]-1)+1);    }  }  return 0;}
0 0
原创粉丝点击