BZOJ3786: 星系探索 splay维护dfs序
来源:互联网 发布:商业银行存贷比数据 编辑:程序博客网 时间:2024/06/05 19:54
题目大意:n个点的树,m个操作
1.询问到根权值和
2.改变父亲,保证不出环
3.子树加
n<=100000,m<=300000,要开long long
toptree轻松虐,可惜我不会
因为本题的询问都是一个点到根的,根又不会变,因此可以通过维护入栈出栈序的方法,每个点入栈时向splay中push _ back一个正权值点,出栈时向splay中push _ back一个负权值点,这样从头到查询点之间的其它点会正负抵消。
改变父亲就将这个点入栈——出栈之间的一段提出来,插到父亲的入栈点之后。
入栈点cnt记为1,出栈点记为-1,则add标记对sum的增加量就是cnt之和*add,入栈点v+=add,出栈点v-=add。
注意权值有0,因此不能靠权值的正负来判断是入栈点还是出栈点,要单独记录。
#include<cstdio>#define gm 100001using namespace std;typedef long long ll;typedef const ll& cref;struct node{ ll sum,v,add; char inv; int cnt; node *s[2],*f; node(); node(cref,char); inline void* operator new(size_t) { static unsigned char p[gm*sizeof(node)*2]; static size_t t=-1; return ((node*)p)+ ++t; } inline bool r() { return this==f->s[1]; } inline void up() { sum=v+s[0]->sum+s[1]->sum; cnt=inv+s[0]->cnt+s[1]->cnt; } inline void plus(cref); inline void down();}*nil=new node;node::node():sum(0),v(0),add(0),cnt(0),f(nil){s[0]=s[1]=nil;}node::node(cref v,char inv):sum(v),v(v),add(0),inv(inv),cnt(inv),f(nil){s[0]=s[1]=nil;}inline void node::plus(cref a){ if(this==nil) return; add+=a; if(~inv) v+=a;else v-=a; sum+=cnt*a;}inline void node::down(){ if(f!=nil) f->down(); if(add) s[0]->plus(add),s[1]->plus(add),add=0;}struct SplayTree{ typedef node* Iterator; node *rt; SplayTree(node *rt=nil):rt(rt){} inline void rot(node *x) { static node *o,*y; static bool k; k=!x->r(); o=x->f,y=x->s[k]; if(o->f!=nil) o->f->s[o->r()]=x; x->s[k]=o,o->s[!k]=y; x->f=o->f,o->f=x,y->f=o; o->up(); } inline void splay(node *x) { x->down(); while(x->f!=nil) { if(x->f->f==nil) rot(x); else if(x->r()==x->f->r()) rot(x->f),rot(x); else rot(x),rot(x); } rt=x; x->up(); } inline void push_back(node *x) { if(rt==nil) {rt=x;return;} node *now=rt; while(now->s[1]!=nil) now=now->s[1]; splay(now); now->s[1]=x; x->f=now; now->up(); } inline node* push_back(cref v,char t) { node *x=new node(v,t); push_back(x); return x; } inline void push_back(SplayTree& v) { push_back(v.rt); v.rt=nil; } inline SplayTree split_before(node *x) { splay(x); x=rt->s[0]; rt->s[0]=x->f=nil; rt->up(); return SplayTree(x); } inline SplayTree split_after(node *x) { splay(x); x=rt->s[1]; rt->s[1]=x->f=nil; rt->up(); return SplayTree(x); } inline void add(cref v) { rt->plus(v); } inline ll sum() { return rt->sum; }}tree;int n,m,fat[gm],w[gm];char c;SplayTree::Iterator begin[gm],end[gm];struct e{ int t; e *n; e(int t,e *n):t(t),n(n){}}*f[gm];void dfs(int x){ begin[x]=tree.push_back(ll(w[x]),1); for(e *i=f[x];i;i=i->n) if(i->t!=fat[x]) dfs(i->t); end[x]=tree.push_back(ll(-w[x]),-1);}inline ll query(int x){ SplayTree arc=tree.split_after(begin[x]); ll ans=tree.sum(); tree.push_back(arc); return ans;}inline void reset(int x,int y){ SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]); pre.push_back(arc); arc=pre.split_after(begin[y]); tree.push_back(arc); pre.push_back(tree); tree.push_back(pre);}inline void add(int x,ll v){ SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]); tree.add(v); tree.push_back(arc); pre.push_back(tree); tree.push_back(pre);}int main(){ scanf("%d",&n); for(int i=2;i<=n;++i) { scanf("%d",fat+i); f[fat[i]]=new e(i,f[fat[i]]); } for(int i=1;i<=n;++i) scanf("%d",w+i); dfs(1); scanf("%d",&m); while(m--) { do c=getchar();while(c!='Q'&&c!='C'&&c!='F'); if(c=='Q') { int d; scanf("%d",&d); printf("%lld\n",query(d)); } else if(c=='C') { int x,y; scanf("%d%d",&x,&y); reset(x,y); } else { int p,q; scanf("%d%d",&p,&q); add(p,q); } } return 0;}
0 0
- Bzoj3786星系探索:splay维护dfs序
- BZOJ3786: 星系探索 splay维护dfs序
- 【bzoj3786】【星系探索】【dfs序+splay】
- [BZOJ3786]星系探索(dfs序+splay)
- BZOJ 3786 星系探索 Splay维护DFS序
- BZOJ 3786 星系探索 splay维护dfs序
- 【BZOJ 3786】星系探索 splay维护dfs序
- BZOJ 3786 星系探索 DFS序+Splay
- bzoj 3786: 星系探索 dfs序+splay
- BZOJ3786 星系探索
- [BZOJ3786]星系探索-ETT
- bzoj3786: 星系探索 //ETT
- bzoj 3786: 星系探索(splay+dfs序)
- BZOJ 3786 星系探索 Splay维护树的入栈出栈序
- bzoj 3786: 星系探索 splay
- BZOJ3786 星系探索 蒟蒻出题人给跪
- splay 动态维护dfs序
- BZOJ 3729 splay维护DFS序+博弈论
- android_09_sd卡可用空间大小
- android 实现点击屏幕其他地方popupwindow消失
- switch语句
- guava-retrying重试工具库: Retryer.call()使用注意事项
- 安装Linux版的Notepad++
- BZOJ3786: 星系探索 splay维护dfs序
- EditText 带边距的背景 drawable
- CSS3的4大伪元素选择器详解
- Java学习(四)
- AndroidStudio&Ecipse最常用的快捷键及对应关系
- Ok框架
- Java - Interface versus Abstract Class
- 提高visual studio使用逼格的连体字(Fira code)以及多行编辑(MixEdit)
- c# xml