雯舞

Love three things int he world -- Manchery

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

怎么萎事啊 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].v

int 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;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许随意转载。 https://blog.csdn.net/u014609452/article/details/71155604
个人分类: LCT
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

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

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭