[LCT 线段树 dfs序] BZOJ 3779 重组病毒

来源:互联网 发布:什么是java框架 编辑:程序博客网 时间:2024/06/04 18:55

%%%PoPoQQQ http://blog.csdn.net/popoqqq/article/details/45919545

”题目大意:给定一棵树,初始每个点都有一个颜色,支持三种操作: 
1.将某个点到根的路径上所有点染上一种新的颜色 
2.将某个点到根的路径上所有点染上一种新的颜色,然后把根设为这个点 
3.定义一个点的代价为这个点到根路径上颜色的种类数,求某个点子树中所有点代价的平均值

容易发现这玩应就是个LCT,操作1就是Access,操作2就是Move_To_Root,代价就是一个点到根路径上的虚边数量+1

我们用LCT模拟上述操作,用线段树维护DFS序维护信息,一旦LCT中出现了虚实边的切换,就在DFS序上对应的子树+1/-1,查询就直接在线段树上查就行了“


#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define V G[p].vusing namespace std;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *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;}inline void read(char *s){char c=nc(); int len=0;for (;!(c>='A' && c<='Z');c=nc());for (len=0;c>='A' && c<='Z';s[++len]=c,c=nc()); s[++len]=0;}const int N=100005;namespace BIT{ #define lowbit(x) ((x)&-(x))ll maxn,c1[N],c2[N];  inline void init(int n){  maxn=n;  }  inline void add(int x,ll r){  for (int i=x;i<=maxn;i+=lowbit(i))  c1[i]+=r,c2[i]+=x*r;  }  inline void add(int l,int r,ll x){if (l>r) return;add(l,x); add(r+1,-x);  }inline ll sum(int x){ll ret1=0,ret2=0;for (int i=x;i;i-=lowbit(i))ret1+=c1[i],ret2+=c2[i];return (x+1)*ret1-ret2;}inline ll sum(int l,int r){if (l>r) return 0;return sum(r)-sum(l-1);}}struct edge{  int u,v,next;  };    edge G[N*2];  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;  }int n,Q,rt;int clk,tid[N],last[N];int fat[N][21],size[N],depth[N];inline void Modify(int x,int val);struct Splay{  struct node{  node *p,*ch[2],*fat;  int size,rev,idx; bool dir() { return this==p->ch[1]; }  void setc(node *c,int d) { ch[d]=c; c->p=this; }  void update(){  size=ch[0]->size+ch[1]->size+1;}   void reverse(){  rev^=1;   swap(ch[0],ch[1]);}void pushdown(node *null)  {  if (rev)   {  if (ch[0]!=null) ch[0]->reverse();  if (ch[1]!=null) ch[1]->reverse();  rev=0;  }}  }*null;  node Mem[N];  Splay(){  null=Mem; null->p=null->ch[0]=null->ch[1]=null; null->size=0;  }  void rot(node *x){  if (x==null) return;  bool d=x->dir(); node *p=x->p;  if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;  p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat);  }  node *stk[N];int pnt;  void splay(node *x){  node *y=x; pnt=0;  while (y!=null) stk[++pnt]=y,y=y->p;  for (int i=pnt;i;i--)   stk[i]->pushdown(null);  while (x->p!=null)  if (x->p->p==null)  rot(x);  else   (x->dir()==x->p->dir())?(rot(x->p),rot(x)):(rot(x),rot(x));  }void Solve(node *x,int val){if (x==null) return; x->pushdown(null);while (x->ch[0]!=null) x=x->ch[0],x->pushdown(null);Modify(x->idx,val);}node *Access(node *x){  node *y=null;  while (x!=null)  {  splay(x);  x->ch[1]->p=null; x->ch[1]->fat=x;;Solve(x->ch[1],1);x->setc(y,1); y->fat=null;  Solve(y,-1);x->update();  y=x; x=x->fat;  }  return y;  }}LCT;  Splay::node *pos[N];  inline void Init(int n){for (int i=1;i<=n;i++)  {  pos[i]=LCT.Mem+i; pos[i]->size=1; pos[i]->idx=i;pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=pos[i]->fat=LCT.null;  }  }inline int dfs(int u,int fa)  {  tid[u]=++clk; size[u]=1; depth[u]=depth[fa]+1; fat[u][0]=fa;for (int k=1;k<=20;k++) fat[u][k]=fat[fat[u][k-1]][k-1];BIT::add(tid[u],tid[u],depth[u]);if (!fa) pos[u]->fat=LCT.null; else pos[u]->fat=pos[fa];for (int p=head[u];p;p=G[p].next)if (V!=fa)size[u]+=dfs(V,u);last[u]=tid[u]+size[u]-1;return size[u];}inline int LCA(int u,int v){      if (depth[u]<depth[v]) swap(u,v);      for (int k=20;~k;k--)          if ((depth[u]-depth[v])&(1<<k))              u=fat[u][k];      if (u==v) return v;      for (int k=20;~k;k--)          if (fat[u][k]!=fat[v][k])              u=fat[u][k],v=fat[v][k];      return fat[u][0];}inline int Fat(int x,int y){for (int k=20;~k;k--)if (depth[fat[x][k]]>depth[y])x=fat[x][k];return x;}inline void Modify(int x,int val){    if(x==rt)    {        BIT::add(1,n,val);        return ;    }    int lca=LCA(x,rt);    if(lca!=x)        BIT::add(tid[x],last[x],val);    else    {    int y=Fat(rt,x);BIT::add(1,tid[y]-1,val);        BIT::add(last[y]+1,n,val);    }}inline ll Sum(int x){if(x==rt)        return BIT::sum(1,n);    int lca=LCA(x,rt);    if(lca!=x)        return BIT::sum(tid[x],last[x]);    else    {    int y=Fat(rt,x);return BIT::sum(1,tid[y]-1)+BIT::sum(last[y]+1,n);    }}inline ll Size(int x){if(x==rt)        return n;    int lca=LCA(x,rt);    if(lca!=x)        return size[x];    else    {    int y=Fat(rt,x);return n-size[y];    }}int main(){int iu,iv,x; char order[10]; ll ret,tot;freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n); read(Q); Init(n); BIT::init(n);for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);dfs(1,0); rt=1;//for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");while (Q--){read(order); read(x);if (!strcmp(order+1,"RELEASE")){LCT.Access(pos[x]);}else if (!strcmp(order+1,"RECENTER")){LCT.Access(pos[x])->reverse(); rt=x;}else if (!strcmp(order+1,"REQUEST")){ret=Sum(x);tot=Size(x);printf("%.10lf\n",(double)ret/tot);}//for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");}return 0;}


0 0
原创粉丝点击