BZOJ 3786 星系探索 splay维护dfs序
来源:互联网 发布:淘宝店铺未来发展趋势 编辑:程序博客网 时间:2024/05/16 23:19
一开始看到子树操作想要树剖,但是仔细想想之后发现树剖没有办法维护一个点到根节点的距离,而且无法维护对应关系,后来就想到了使用dfs序,这样只要维护前缀和就可以快速求出一个点到根节点的距离,由于有换边操作,所以我们要使用splay维护,这道题要注意一个细节,就是每次想要提取出来一个区间需要先找到这个区间的前驱后继,都做完以后这题就能过啦
#include<cstdio>#include<cstdlib>#include<ctime>#include<cmath>#include<cstring>#include<string>#include<iostream>#include<iomanip>#include<algorithm>using namespace std;typedef long long ll;struct splay{ splay *fa,*ls,*rs; ll v,sum,zsize,fsize,add_mark; bool pr; splay(); void push_up(); void add_v(ll val); void push_down();}*null=new splay(),mempool[300000],*root;int dfsx[300000];int in_t[300000];int out_t[300000];int fir[300000];int nex[300000];struct bian{ int r;}a[600000];int topppp;ll v[300000];int top=0;void dfs(int u,int fro){ dfsx[++top]=u; in_t[u]=top; for(int o=fir[u];o!=0;o=nex[o]) if(a[o].r!=fro) dfs(a[o].r,u); dfsx[++top]=u; out_t[u]=top;}void splay :: push_up(){ sum=ls->sum+v+rs->sum; zsize=ls->zsize+pr+rs->zsize; fsize=ls->fsize+(1-pr)+rs->fsize;}void splay :: push_down(){ if(add_mark) { if(ls!=null) ls->add_v(add_mark); if(rs!=null) rs->add_v(add_mark); add_mark=0; }}void splay :: add_v(ll val){ if(pr) v+=val; else v-=val; sum+=(zsize-fsize)*val; add_mark+=val;}splay :: splay(){ fa=ls=rs=null; v=sum=zsize=fsize=add_mark=pr=0;}void right(splay *x){ splay *y=x->fa; y->ls=x->rs; x->rs->fa=y; x->rs=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->push_up(); if(y==root) root=x;}void left(splay *x){ splay *y=x->fa; y->rs=x->ls; x->ls->fa=y; x->ls=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->push_up(); if(y==root) root=x;}void push_down(splay *x){ if(x->fa!=null) push_down(x->fa); x->push_down();}void splaying(splay *x,splay *goal){ push_down(x); while(1) { splay *y=x->fa; splay *z=y->fa; //cout<<x<<" "<<y->rs<<endl;//<<null<<" "<<endl; if(y==goal) break; if(z==goal) { if(x==y->ls) right(x); else left(x); break; } if(x==y->ls) { if(y==z->ls) right(y); right(x); } else if(x==y->rs) { if(y==z->rs) left(y); left(x); } } x->push_up();}splay *maketree(int l,int r){ if(l>r) return null; int mid=l+r>>1; splay *x=&mempool[mid]; if(mid==in_t[dfsx[mid]]) { x->v=v[dfsx[mid]]; x->sum=v[dfsx[mid]]; x->pr=true; x->zsize=1; } else { x->v=-v[dfsx[mid]]; x->sum=-v[dfsx[mid]]; x->pr=false; x->fsize=1; } x->ls=maketree(l,mid-1); x->ls->fa=x; x->rs=maketree(mid+1,r); x->rs->fa=x; x->push_up(); return x;}splay* find_hou(splay *o){ if(o->ls!=null) return find_hou(o->ls); return o;}splay* find_qian(splay *o){ if(o->rs!=null) return find_qian(o->rs); return o;}ll find_ans(int x){ splaying(&mempool[in_t[1]],null); splay *mid=find_qian(root->ls); splaying(&mempool[in_t[x]],null); splay *midd=find_hou(root->rs); splaying(mid,null); splaying(midd,root); return root->rs->ls->sum;}void change(int x,int v){ splaying(&mempool[in_t[x]],null); splay *mid=find_qian(root->ls); splaying(&mempool[out_t[x]],null); splay *midd=find_hou(root->rs); splaying(mid,null); splaying(midd,root); root->rs->ls->add_v(v); root->rs->push_up(); root->push_up();}void move_to_wz(int x,int y){ splaying(&mempool[in_t[x]],null); splay *mid=find_qian(root->ls); splaying(&mempool[out_t[x]],null); splay *midd=find_hou(root->rs); splaying(mid,null); splaying(midd,root); splay *qie=root->rs->ls; qie->fa=null; root->rs->ls=null; root->rs->push_up(); root->push_up(); splaying(&mempool[in_t[y]],null); splay *middd=find_hou(root->rs); splaying(middd,root); root->rs->ls=qie; qie->fa=root->rs; root->rs->push_up(); root->push_up();}void add_edge(int l,int r){ //cout<<l<<" "<<r<<endl; a[++topppp].r=r; nex[topppp]=fir[l]; fir[l]=topppp;}char s[10];int main(){ ll n,m; scanf("%lld",&n); for(int i=1;i<n;i++) { int x; scanf("%d",&x); add_edge(x,i+1); } for(int i=1;i<=n;i++) scanf("%lld",&v[i]); dfs(1,0); root=maketree(0,top+1); scanf("%lld",&m); for(int i=1;i<=m;i++) { scanf("%s",s); if(s[0]=='Q') { int x; scanf("%d",&x); printf("%lld\n",find_ans(x)); } else if(s[0]=='F') { ll x,val; scanf("%lld%lld",&x,&val); change(x,val); } else { int x,y; scanf("%d%d",&x,&y); move_to_wz(x,y); } }}
1 1
- BZOJ 3786 星系探索 Splay维护DFS序
- BZOJ 3786 星系探索 splay维护dfs序
- 【BZOJ 3786】星系探索 splay维护dfs序
- BZOJ 3786 星系探索 DFS序+Splay
- bzoj 3786: 星系探索 dfs序+splay
- Bzoj3786星系探索:splay维护dfs序
- BZOJ3786: 星系探索 splay维护dfs序
- bzoj 3786: 星系探索(splay+dfs序)
- BZOJ 3786 星系探索 Splay维护树的入栈出栈序
- bzoj 3786: 星系探索 splay
- 【bzoj3786】【星系探索】【dfs序+splay】
- [BZOJ3786]星系探索(dfs序+splay)
- BZOJ 3786: 星系探索
- BZOJ 3786 星系探索
- BZOJ 3729 splay维护DFS序+博弈论
- splay 动态维护dfs序
- BZOJ 1251 Splay维护序列
- BZOJ 3323 splay维护序列
- 1.MATLAB图像处理基础知识
- 数据结构课程设计--电子投票系统
- JavaWeb中request与response的认知
- 数据分析的几个问题
- WebView 学习笔记
- BZOJ 3786 星系探索 splay维护dfs序
- 本地工程不要上传到svn(git)的文件和目录
- 利用Intellij+MAVEN完成Spring整合Mybatis项目详解
- 联合索引和分别建立索引的比较
- 杭电2027
- Java入门学习记录2
- VB.NET的几种延时方法
- 调整内核printk的打印级别
- selenium监控回家火车票