bzoj3786 星际探索 splay dfs序
这道题 首先 因为他求的是当前点到根节点的路径和 我们可以将题目转换为括号序列的写法 将点拆为左括号以及右括号 左括号为正 右括号为负 这样题目就变为了求前缀和了 如果一个点是这个点的子树 那么他的左右括号就一定包含在所求区间里 会被抵消掉而不影响结果。 这样我们可以利用dfs序建树 操作为区间加 单点修改 树的合并以及分裂 一起区间和 当然区间加因为我们维护的是括号序列 所以区间加的时候我们就要将左括号加w而右括号减w 但是我们因此我们还要记录这个点子树及其本身的左右括号差 区间加就加上左括号数减右括号数的差 乘以w就可以了 当然还要维护这两个括号本身的信息 毕竟这是一个闭区间 区间的分裂和合并的话 (左括号为x 右括号为y) 将x旋到root 切开他的左子树 左子树根为p1 将y旋到root 切开他的右子树 右子树跟为p3 xy所在的树跟为p3 然后将p1和p3合并 合并的话将p1的树上最右下方的点旋到p1 这样他就不存在右子树 强制将p3连到右子树 然后将新的依赖关系的点k旋到p1 切开右子树 强制讲p2连到右子树 然后按前面的方法把剩下的两棵树连在一起 就okay了 说起来难其实就三个函数的事情 不超过二十行 看代码比较好理解呐 剩下的加油咯
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int M=;
- int read(){
- int ans=,f=,c=getchar();
- while(c<''||c>''){if(c=='-') f=-; c=getchar();}
- while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
- return ans*f;
- }
- long long tag[M],v[M],ans[M];
- int tot,n,m,root,d[M],q[M],fa[M],pd[M];
- int first[M],sum,c[M][];
- struct node{int to,next,w;}e[M];
- void insert(int a,int b){sum++; e[sum].to=b; e[sum].next=first[a]; first[a]=sum;}
- void add(int z,long long w){
- if(!z) return ;
- tag[z]+=w;
- v[z]+=w*pd[z];
- ans[z]+=w*d[z];
- }
- void qadd(int z,int w){
- if(!z) return ;
- v[z]+=w*pd[z];
- ans[z]+=w*pd[z];
- }
- void up(int k){
- int l=c[k][],r=c[k][];
- d[k]=pd[k]+d[l]+d[r];
- ans[k]=ans[l]+ans[r]+v[k];
- }
- void down(int k){
- if(tag[k]){
- add(c[k][],k[tag]);
- add(c[k][],k[tag]);
- tag[k]=;
- }
- }
- void rotate(int x,int& k){
- int y=fa[x],z=fa[y],l=,r=;
- if(c[y][]==x) l=,r=;
- if(y==k) k=x;
- else{if(c[z][]==y) c[z][]=x; else c[z][]=x;}
- fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
- c[y][l]=c[x][r]; c[x][r]=y;
- up(y); up(x);
- }
- int stk[M],stp=;
- void sp(int x,int& k){
- for(int w=x;w;w=w[fa])stk[stp++]=w;
- while(stp)down(stk[--stp]);
- while(x!=k){
- int y=fa[x],z=fa[y];
- if(y!=k){
- if(c[z][]==y^c[y][]==x) rotate(y,k);
- else rotate(x,k);
- }
- rotate(x,k);
- }
- }
- void dfs(int k){
- q[++tot]=k;
- for(int i=first[k];i;i=e[i].next) dfs(e[i].to);
- q[++tot]=k+n;
- }
- int build(int l,int r){
- if(l>r) return ;
- int m=(l+r)>>,now=q[m];
- c[now][]=build(l,m-);
- c[now][]=build(m+,r);
- for(int i=;i<;i++) if(c[now][i]) fa[c[now][i]]=now;
- up(now);
- return now;
- }
- int find(int k){
- while(c[k][]) k=c[k][];
- return k;
- }
- void cut_l(int x,int rt,int& r1,int& r2){
- sp(x,rt);
- r1=c[x][]; r2=x;
- c[r2][]=fa[r1]=;
- up(x);
- }
- void cut_r(int x,int rt,int& r1,int& r2){
- sp(x,rt);
- r1=x; r2=c[x][];
- c[r1][]=fa[r2]=;
- up(x);
- }
- int mg(int r1,int r2){
- int w=find(r1);
- sp(w,r1);
- c[w][]=r2;fa[r2]=w;
- up(w);
- return w;
- }
- void papa(int x,int f){
- int y=x+n,p1,p2,p3;
- cut_l(x,root,p1,p2);
- cut_r(y,p2,p2,p3);
- cut_r(f,mg(p1,p3),p1,p3);
- root=mg(mg(p1,p2),p3);
- }
- int main()
- {
- int k,w;
- char ch[];
- n=read();
- for(int i=;i<=n;i++) k=read(),insert(k+,i+);
- for(int i=;i<=n+;i++) w=read(),v[i]=w,v[i+n]=-w,pd[i]=,pd[i+n]=-;
- q[++tot]=; dfs(); q[++tot]=*n+;
- root=build(,*n+);
- m=read();
- while(m--){
- scanf("%s",ch);
- if(ch[]=='Q'){k=read()+; sp(k,root); printf("%lld\n",ans[c[k][]]+v[k]);}
- if(ch[]=='C'){ int x=read()+,y=read()+; papa(x,y);}
- if(ch[]=='F'){
- k=read()+; w=read();
- int y=k+n,z;
- sp(k,root); sp(y,c[root][]);
- z=c[y][];
- qadd(k,w); qadd(y,w);
- add(z,w);
- up(y); up(k);
- }
- }
- return ;
- }
bzoj3786 星际探索 splay dfs序的更多相关文章
- BZOJ3786: 星系探索 Splay+DFS序
题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...
- 【BZOJ-3786】星系探索 Splay + DFS序
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 647 Solved: 212[Submit][Status][Discuss] ...
- BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...
- BZOJ3786:星系探索(Splay,括号序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- bzoj3786星系探索 splay
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1314 Solved: 425[Submit][Status][Discuss ...
- BZOJ_3729_Gty的游戏_博弈论+splay+dfs序
BZOJ_3729_Gty的游戏_博弈论+splay+dfs序 Description 某一天gty在与他的妹子玩游戏. 妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子 ...
- BZOJ3786 星际探索
@(BZOJ)[DFS序, Splay] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其 ...
- 【NOI2019集训题2】 序列 后缀树+splay+dfs序
题目大意:给你一个长度为$n$的序列$a_i$,还有一个数字$m$,有$q$次询问 每次给出一个$d$和$k$,问你对所有的$a_i$都在模$m$意义下加了$d$后,第$k$小的后缀的起点编号. 数据 ...
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
随机推荐
- lnmp操作
LNMP 1.2+状态管理: lnmp {start|stop|reload|restart|kill|status}LNMP 1.2+各个程序状态管理: lnmp {nginx|mysql|mari ...
- python语法join函数
Python语法中join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串. vid = )
- python基础——元组、文件及其它
Python核心数据类型--元组 元组对象(tuple)是序列,它具有不可改变性,和字符串类似.从语法上讲,它们便在圆括号中,它们支持任意类型.任意嵌套及常见的序列操作. 任意对象的有序集合:与字符串 ...
- C#的内存管理
栈的填充方式是从高到低,高数位到低数位的填充 堆的填充方式是从低向高,低数位到高数位的填充 内存堆上没有被栈引用的东西,才会被垃圾回收器回收. GC垃圾自动回收会重新排列堆里面的内存占用,自动回收运行 ...
- jmeter接口测试--响应结果Unicode转码成中文
jmeter接口测试-响应结果Unicode转码成中文 一般情况下,接口返回数据都会经过加密,所以有时相应结果会显示为Unicode,因此,需添加BeanShell PostProcessor,加入代 ...
- pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
pandas DataFrame的增删查改总结系列文章: pandas DaFrame的创建方法 pandas DataFrame的查询方法 pandas DataFrame行或列的删除方法 pand ...
- HDU 4747 Mex(线段树)(2013 ACM/ICPC Asia Regional Hangzhou Online)
Problem Description Mex is a function on a set of integers, which is universally used for impartial ...
- Alpha项目冲刺(团队作业5)
团队成员 组 员 学号 朱世杰 211414141 曹晔宁 211306302 一.冲刺(7次 Scrum) [Alpha版本]冲刺阶段--Day 1 [Alpha版本]冲刺阶段--Day 2 [Al ...
- DataGridView加载gif图片
当我们想加载图片时,一般情况下都会使用picturebox控件,这个控件可以加载各种格式的图片,当然也包括gif图片.但是有时,我们也希望一些数据展示控件也可以加载图片,比如说DataGridView ...
- Redis数据类型及操作详解
Redis数据库,是nosql的一种.与传统关系型数据库(如mysql.sqlserver等)相比,他在处理大数据量上相当有优势,扩展性和可用性高,这是传统型数据库所达不到的. Redis是一个key ...