题目大意:给你一棵树,支持一下三种操作

1.获取某节点到根节点的路径上所有节点的权值和

2.更换某棵子树的父亲

3.某子树内所有节点的权值都增加一个值w

当时想到了splay维护dfs序,查完题解发现思路是对的,然后我就写了足足6个小时才A

st[x]代表入栈时间,ed[x]代表出栈时间

对于第一个操作,每个树上节点在splay中都有两个位置,分别对应入栈出栈序,然后把入栈的点权*1,出栈点权*-1,就可以避免其它子树干扰了

接着查询到根节点的路径权值和呢,splay把1~st[x]整个序列都扔到一个子树里,求一下子树权值和即可

第二个操作,可以找一下st[x]和ed[x]对应splay中节点的前驱和后继,把它们都搞到一个splay子树里,在把整棵树接到要求的父节点即可

第三个操作,和第二个操作类似,找前驱后继然后在子树打标记即可,此外,还要维护splay子树内的入栈节点数-出栈节点数来直接得到splay子树的权值和。

注意,一定要在所有能传标记的地方都传标记,不论是从下往上splay,还是从上到下找前驱or后继,而如果不在找前驱后继的过程中下传标记,上层的标记无法被传到下层,导致结果错误!就这个错误我调了2个小时!

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200100
#define il inline
#define ll long long
#define root d[0].ch[1]
using namespace std; char q[];
int n,m,cte,tot;
int st[N],ed[N],head[N],sq[N];
ll w[N];
struct EDGE{int to,nxt;}edge[N];
struct SPLAY{int fa,ch[],ss,fl;ll val,sum,tag;}d[N];
il int idf(int x){return d[d[x].fa].ch[]==x?:;}
il void con(int x,int ff,int p){d[ff].ch[p]=x;d[x].fa=ff;}
il void pushup(int x){
d[x].sum=d[d[x].ch[]].sum+d[d[x].ch[]].sum+d[x].val;
d[x].ss=d[d[x].ch[]].ss+d[d[x].ch[]].ss+d[x].fl;
}
il void pushdown(int x){
if(!d[x].tag) return;
int ls=d[x].ch[],rs=d[x].ch[];
d[ls].tag+=d[x].tag,d[rs].tag+=d[x].tag;
d[ls].val+=d[x].tag*(ll)d[ls].fl,d[rs].val+=d[x].tag*(ll)d[rs].fl;
d[ls].sum+=d[x].tag*(ll)d[ls].ss,d[rs].sum+=d[x].tag*(ll)d[rs].ss;
d[x].tag=;
}
il void rot(int x){
int y=d[x].fa;int ff=d[y].fa;int px=idf(x);int py=idf(y);
pushdown(y),pushdown(x);
con(d[x].ch[px^],y,px),con(y,x,px^),con(x,ff,py);
pushup(y),pushup(x);
}
il void splay(int x,int to){
to=d[to].fa;
while(d[x].fa!=to){
int y=d[x].fa;
if(d[y].fa==to) rot(x);
else if(idf(x)==idf(y)) rot(y),rot(x);
else rot(x),rot(x);}
}
int gc(){
int rett=,fh=;char p=getchar();
while(p<''||p>''){if(p=='-')fh=-;p=getchar();}
while(p>=''&&p<=''){rett=(rett<<)+(rett<<)+p-'';p=getchar();}
return rett*fh;
}
void ae(int u,int v){
cte++;edge[cte].to=v;
edge[cte].nxt=head[u];head[u]=cte;
}
void dfs1(int u,int ff)
{
st[u]=++tot,sq[tot]=u,d[tot].val=w[u],d[tot].fl=;
for(int j=head[u];j!=-;j=edge[j].nxt){
int v=edge[j].to;
if(v==ff) continue;
dfs1(v,u);}
ed[u]=++tot,sq[tot]=u,d[tot].val=-w[u],d[tot].fl=-;
}
int build(int l,int r)
{
if(l>r) return ;
int mid=(l+r)>>;
con(build(l,mid-),mid,);
con(build(mid+,r),mid,);
pushup(mid);
return mid;
}
int lower(int x)
{
pushdown(x),x=d[x].ch[];
while(x){
pushdown(x);
if(d[x].ch[]) x=d[x].ch[];
else break;}
return x;
}
int upper(int x)
{
pushdown(x),x=d[x].ch[];
while(x){
pushdown(x);
if(d[x].ch[]) x=d[x].ch[];
else break;}
return x;
}
ll query(int x)
{
splay(st[],root);
splay(st[x],d[root].ch[]);
int lw=upper(st[x]);
splay(lw,d[root].ch[]);
return d[d[lw].ch[]].sum;
}
void add(int x,ll ww)
{
int trl,trr,rt;
splay(st[x],root);
splay(ed[x],d[root].ch[]);
trl=lower(st[x]);
splay(trl,root);
trr=upper(ed[x]);
splay(trr,d[root].ch[]);
rt=d[trr].ch[];
d[rt].val+=ww*(ll)d[rt].fl;
d[rt].sum+=ww*(ll)d[rt].ss;
d[rt].tag+=ww;
}
void mov(int x,int y)
{
int trl,trr,frt,rtt;
splay(st[x],root);
splay(ed[x],d[root].ch[]);
trl=lower(st[x]);
splay(trl,root);
trr=upper(ed[x]);
splay(trr,d[root].ch[]);
pushdown(trl),pushdown(trr);
rtt=d[trr].ch[];
d[trr].ch[]=,d[rtt].fa=;
pushup(trr),pushup(trl); splay(st[y],root);
splay(ed[y],d[root].ch[]);
trl=lower(ed[y]);
if(trl) con(rtt,trl,);
else con(rtt,ed[y],);
splay(rtt,root);
}
void print(int x)
{
if(d[x].ch[]) print(d[x].ch[]);
printf("%d ",sq[x]);
if(d[x].ch[]) print(d[x].ch[]);
} int main()
{
scanf("%d",&n);
int x,y;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)
x=gc(),ae(x,i),ae(i,x);
for(int i=;i<=n;i++)
w[i]=gc();
st[]=++tot,dfs1(,-),ed[]=++tot;
root=build(,tot);
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%s",q);
if(q[]=='Q'){
x=gc();
printf("%lld\n",query(x));
}else if(q[]=='F'){
x=gc(),y=gc();
add(x,(ll)y);
}else{
x=gc(),y=gc();
mov(x,y);
}
}
/*for(int i=1;i<=n;i++)
printf("%lld %lld %lld\n",query(i),d[st[i]].val,d[ed[i]].val);*/
return ;
}

BZOJ 3786 星系探索 (splay+dfs序)的更多相关文章

  1. 【BZOJ-3786】星系探索 Splay + DFS序

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 647  Solved: 212[Submit][Status][Discuss] ...

  2. BZOJ3786: 星系探索 Splay+DFS序

    题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲. 分析: 看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊... 那么,考虑更换一个点的父亲这个操作很有意思, ...

  3. BZOJ 3786 星系探索 ——Splay

    子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...

  4. bzoj 3786 星系探索 dfs+splay

    [BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...

  5. BZOJ 3786: 星系探索 解题报告

    3786: 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅 ...

  6. BZOJ 3786 星系探索

    Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...

  7. bzoj3786 星际探索 splay dfs序

    这道题 首先 因为他求的是当前点到根节点的路径和 我们可以将题目转换为括号序列的写法 将点拆为左括号以及右括号 左括号为正 右括号为负 这样题目就变为了求前缀和了 如果一个点是这个点的子树 那么他的左 ...

  8. BZOJ3786:星系探索(Splay,括号序)

    Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...

  9. BZOJ 3786: 星系探索 欧拉游览树

    一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序 #include <cstring> #include <algorithm> ...

随机推荐

  1. Jquery 根据HTML内容选择元素

    选择所有包含 "is" 的 元素: $("p:contains(is)")

  2. 01.Python基础-3.集合容器

    1 列表list 1.1 列表介绍 Python内置的一种数据类型是列表:list. 有序的集合,可随时添加和删除其中的元素. 每个元素都分配一个数字 --它的位置,或索引.0,1,2,3-- 可存放 ...

  3. 探索Python的多态是怎么实现的

    多态是指通过基类的指针或者引用,在运行时动态调用实际绑定对象函数的行为. 对于其他如C++的语言,多态是通过在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来 ...

  4. Dubbo&Zookeeper运行原理

    Dubbo是一个分布式服务框架,Dubbo的架构如图所示: 节点角色说明: Provider: 暴露服务的服务提供方. Consumer: 调用远程服务的服务消费方. Registry: 服务注册与发 ...

  5. PHP学习总结(6)——PHP入门篇之PHP语句结束符

    PHP语句结束符 有的小伙伴们是不是已经注意在每一条PHP代码行结尾处都会有一个分号:.对的,这点注意,在PHP编程中需要在每条语句的末尾加入分号:.但要注意,分号:一定在半角状态下输入噢.

  6. 你必须搞清楚的String,StringBuilder,StringBuffer

    String,StringBuilder 以及 StringBuffer 这三个类的关系与区别一直是 Java 的经典问题,这次就来讲一下关于这三个类的一些知识 一. 简单对比 String : 字符 ...

  7. ie6 bug 收集

    1.IE6中奇数宽高的BUG IE6下查看,变成了right:1px的效果了: IE6还有奇数宽高的bug,解决方案就是将外部相对定位的div宽度改成偶数.高度也是一样的查看源码: CSS代码: #o ...

  8. 04springMVC数据类型转换

    数据类型转换简介 Spring Web MVC中的数据类型转换 内建的类型转换器 自定义类型转换器 1      数据类型转换简介 当从页面提交数据到后台Action的时候,通过请求发送的数据,通常都 ...

  9. add Admob with Cocos2d-x on iOS

    add Admob with Cocos2d-x on iOS (2013-02-27 14:12:00) 转载▼ 标签: c=blog&q=it&by=tag" targe ...

  10. 利用POI操作不同版本号word文档中的图片以及创建word文档

    我们都知道要想利用java对office操作最经常使用的技术就应该是POI了,在这里本人就不多说到底POI是什么和怎么用了. 先说本人遇到的问题,不同于利用POI去向word文档以及excel文档去写 ...