BZOJ 3779 重组病毒 LCT维护子树信息
2017-04-07 09:52
393 查看
题目大意:给定一棵树,要求支持:将某个点到根的路径染色;换根后将原来的根到现在的根的路径染色;求某个点的子树到根的平均颜色段数
比较麻烦的LCT维护子树信息
变量名是照neither_nor神犇抄的..意义相同,链接
因为要计算子树到根的平均颜色段数,所以要维护子树到(子树的)根的颜色段数和(Col),Splay在原树中代表的链的颜色段数(cols),子树size(rsiz)。
其实就是把子树到当前根的颜色段数和分成子树到子树根和子树根到当前根两部分。将想要查询的子树根Access+Splay后,Col即为子树内颜色段数和,cols即为子树根到当前根。
而要维护Col,就要维护coll/colr,sumCol,sCol,sumCol
具体的更新关系为:
coll->Col (update)
colr->coll (rev)
sumCol->coll/colr (color)
sCol->Col / sumsCol->sumCol (color)
Col->coll/colr (maintain)
Col->sumCol / sCol->sumsCol (maintain)
coll->colr / colr->coll (maintain)
将变量整理后,
正常Splay信息:siz,v,lv,rv,cols
虚子树信息:xsiz,Col,sCol
LCT子树信息:rsiz,coll,colr,sumCol,sumsCol
比较麻烦的LCT维护子树信息
变量名是照neither_nor神犇抄的..意义相同,链接
因为要计算子树到根的平均颜色段数,所以要维护子树到(子树的)根的颜色段数和(Col),Splay在原树中代表的链的颜色段数(cols),子树size(rsiz)。
其实就是把子树到当前根的颜色段数和分成子树到子树根和子树根到当前根两部分。将想要查询的子树根Access+Splay后,Col即为子树内颜色段数和,cols即为子树根到当前根。
而要维护Col,就要维护coll/colr,sumCol,sCol,sumCol
具体的更新关系为:
coll->Col (update)
colr->coll (rev)
sumCol->coll/colr (color)
sCol->Col / sumsCol->sumCol (color)
Col->coll/colr (maintain)
Col->sumCol / sCol->sumsCol (maintain)
coll->colr / colr->coll (maintain)
将变量整理后,
正常Splay信息:siz,v,lv,rv,cols
虚子树信息:xsiz,Col,sCol
LCT子树信息:rsiz,coll,colr,sumCol,sumsCol
#include <cstdio> #include <algorithm> #define N 100005 #define int long long using namespace std; typedef long long LL; struct Node { Node *ch[2],*pa; int dir() { return pa->ch[0]==this ? 0 : pa->ch[1]==this ? 1 : -1; } ///Basic Splay varieties int siz,xsiz,rsiz,v,lv,rv,cols; ///color information int coll,colr,Col,sumCol,sCol,sumsCol; ///mark int color_mark; bool rev_mark; ///function Node(); void rev(); void color(int); void pushdown(); void maintain(); void update(Node*,int); }*null=new Node(),p ; Node :: Node():rev_mark(false),color_mark(0),xsiz(0) { pa=ch[0]=ch[1]=null; siz=null?1:0; rsiz=siz; v=lv=rv=coll=colr=cols=Col=sumCol=sCol=sumsCol=0; } void Node :: rev() { if(this==null) return ; swap(ch[0],ch[1]); swap(lv,rv); swap(coll,colr); rev_mark=!rev_mark; return ; } void Node :: color(int x) { if(this==null) return ; v=lv=rv=color_mark=x; cols=1; coll=colr=siz+sumCol+sumsCol; Col+=sCol; sumCol+=sumsCol; sCol=sumsCol=0; return ; } void Node :: pushdown() { if(rev_mark) { ch[0]->rev(); ch[1]->rev(); rev_mark=false; } if(color_mark) { ch[0]->color(color_mark); ch[1]->color(color_mark); color_mark=0; } return ; } void Node :: maintain() { if(this==null) return ; siz=ch[0]->siz+ch[1]->siz+1; rsiz=ch[0]->rsiz+ch[1]->rsiz+1+xsiz; lv=rv=v; cols=1; coll=colr=Col+1; sumCol=Col+ch[0]->sumCol+ch[1]->sumCol; sumsCol=sCol+ch[0]->sumsCol+ch[1]->sumsCol; if(ch[0]!=null) { cols+=ch[0]->cols-(ch[0]->rv==v); lv=ch[0]->lv; coll+=ch[0]->coll+ch[0]->cols*(xsiz+1); int tmp=ch[1]->cols+(ch[1]->lv!=v); colr+=ch[0]->colr+tmp*ch[0]->rsiz; if(ch[0]->rv==v) coll-=1+xsiz, colr-=ch[0]->rsiz; } if(ch[1]!=null) { cols+=ch[1]->cols-(ch[1]->lv==v), rv=ch[1]->rv; colr+=ch[1]->colr+ch[1]->cols*(xsiz+1); int tmp=ch[0]->cols+(ch[0]->rv!=v); coll+=ch[1]->coll+tmp*ch[1]->rsiz; if(ch[1]->lv==v) colr-=1+xsiz, coll-=ch[1]->rsiz; } return ; } void Node :: update(Node* o,int k) { xsiz+=k*o->rsiz, rsiz+=k*o->rsiz; Col+=k*o->coll, sumCol+=k*o->coll, coll+=k*o->coll, colr+=k*o->coll; if(v!=o->lv) Col+=k*o->rsiz, sumCol+=k*o->rsiz, coll+=k*o->rsiz, colr+=k*o->rsiz; else sCol+=k*o->rsiz, sumsCol+=k*o->rsiz; return ; } void Rotate(Node* o,int d) { Node* k=o->ch[d^1]; int d2; o->ch[d^1]=k->ch[d]; k->ch[d]->pa=o; k->ch[d]=o; o->maintain(), k->maintain(); if(~(d2=o->dir())) o->pa->ch[d2]=k; k->pa=o->pa, o->pa=k; return ; } void To_pushdown(Node* o) { static Node* q ; int top=0; while(~(o->dir())) q[++top]=o, o=o->pa; q[++top]=o; while(top) q[top--]->pushdown(); return ; } void Splay(Node* o) { To_pushdown(o); int d; while(~(d=o->dir())) { if(o->pa->dir()==d) Rotate(o->pa->pa,d^1); Rotate(o->pa,d^1); } return ; } void Access(Node* o) { Node* p=null; while(o!=null) { Splay(o); o->update(o->ch[1],1), o->update(p,-1); o->ch[1]=p, o->maintain(); p=o; o=o->pa; } return ; } void Move_to_root(Node* o) { Access(o), Splay(o); o->rev(); return ; } void Link(Node* x,Node* y) { Move_to_root(x); Move_to_root(y); x->pa=y; y->update(x,1); return ; } int n,m,T; void request(Node* o) { Access(o), Splay(o); int ans=o->Col+1,anst=o->xsiz+1,ans2=o->cols; ans+=anst*(ans2-1); printf("%.10f\n",1.0*ans/anst); return ; } void release(Node* o) { Access(o), Splay(o); o->color(++T); return ; } void recenter(Node* o) { Move_to_root(o); o->color(++T); return ; } main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) p[i].color(++T); for(int i=1;i<n;i++) { int x,y; scanf("%lld%lld",&x,&y); Link(p+x,p+y); } Move_to_root(p+1); while(m--) { char mode[10]; int x; scanf("%s%lld",mode,&x); if(mode[2]=='Q') request(p+x); else if(mode[2]=='L') release(p+x); else recenter(p+x); } return 0; }
相关文章推荐
- bzoj3510首都 LCT维护子树信息+启发式合并
- [BZOJ4530][Bjoi2014][LCT维护子树信息]大融合
- BZOJ 3779 重组病毒 LCT+线段树维护DFS序
- bzoj 4530: [Bjoi2014]大融合 lct维护子树信息
- BZOJ 4530 [Bjoi2014]大融合 LCT维护子树信息
- [BZOJ]4530 [BJOI2014] 大融合 LCT维护子树信息
- BZOJ 4530: [Bjoi2014]大融合 lct维护子树信息
- [LCT 线段树 dfs序] BZOJ 3779 重组病毒
- 【bzoj 4530】大融合(LCT维护子树信息)
- 【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息
- 【LCT维护子树信息】BZOJ4530(Bjoi2014)[大融合]题解
- BZOJ4530 BJOI 2014 大融合 LCT维护子树信息
- [BZOJ3510][启发式合并][LCT维护子树信息]首都
- 【BZOJ4530】[Bjoi2014]大融合 LCT维护子树信息
- 【BZOJ3510】首都 LCT维护子树信息+启发式合并
- 【bzoj3510】首都 LCT维护子树信息(+启发式合并)
- bzoj 3779: 重组病毒【LCT+线段树维护dfs序】
- [BZOJ4530]-大融合-LCT维护子树信息
- BZOJ 3779 重组病毒 ——LCT 线段树
- BZOJ 3510: 首都 LCT维护子树信息 启发式合并