子树可以移动,唔。

还是用Splay维护DFS序即可。

子树的话直接截取出来就好了。

然后求前驱后继可能麻烦一些。

添加两个虚拟节点会比较好写。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 300005 int n,fa[maxn],st[maxn],top=0,id[maxn],rt,m;
int pos[maxn][2],w[maxn],ch[maxn][2],pn[maxn],siz[maxn][2];
int sta[maxn],cnt=0;
ll val[maxn],sum[maxn],tag[maxn];
char opt[11]; vector <int> v[maxn]; void update(int x)
{
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
siz[x][0]=siz[ch[x][0]][0]+siz[ch[x][1]][0];
siz[x][1]=siz[ch[x][0]][1]+siz[ch[x][1]][1];
if (pn[x]==-1) siz[x][0]++;
else if (pn[x]==1) siz[x][1]++;
} int build(int l,int r,int f)
{
if (l>r) return 0;
int mid=(l+r)/2;
fa[mid]=f;
if (st[mid]<0)
{
pos[-st[mid]][1]=mid;
val[mid]=-w[-st[mid]];
pn[mid]=-1;
}
else if (st[mid]>0)
{
pos[st[mid]][0]=mid;
val[mid]=w[st[mid]];
pn[mid]=1;
}
else if (st[mid]==0)
{
pos[st[mid]][0]=mid;
val[mid]=0;
pn[mid]=0;
}
ch[mid][0]=build(l,mid-1,mid);
ch[mid][1]=build(mid+1,r,mid);
update(mid);
return mid;
} void dfs(int o)
{
st[++top]=o;
for (int i=0;i<v[o].size();++i) dfs(v[o][i]);
st[++top]=-o;
} void Debug(int o)
{
if (!o) return ;
printf("|-----------------| \n");
printf("Node %d : \n",o);
printf("Fa %d Ch l - %d Ch r - %d\n",fa[o],ch[o][0],ch[o][1]);
printf("Val %lld Sum %lld Positive Negetive %d\n",val[o],sum[o],pn[o]);
Debug(ch[o][0]);
Debug(ch[o][1]);
} void pushdown(int x)
{
if (tag[x])
{
tag[ch[x][0]]+=tag[x];
tag[ch[x][1]]+=tag[x];
val[ch[x][0]]+=pn[ch[x][0]]*tag[x];
val[ch[x][1]]+=pn[ch[x][1]]*tag[x];
sum[ch[x][0]]+=1LL*(siz[ch[x][0]][1]-siz[ch[x][0]][0])*tag[x];
sum[ch[x][1]]+=1LL*(siz[ch[x][1]][1]-siz[ch[x][1]][0])*tag[x];
tag[x]=0;
}
} void rot(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0; else l=1; r=l^1;
if (y==k) k=x;
else
{
if (ch[z][0]==y) ch[z][0]=x;
else ch[z][1]=x;
}
fa[x]=z; fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r]; ch[x][r]=y;
update(y);update(x);
} void splay(int x,int &k)
{
sta[cnt=1]=x;
for (int i=x;i!=k;i=fa[i]) sta[++cnt]=fa[i];
while (cnt) pushdown(sta[cnt--]); while(x!=k)
{
int y=fa[x];
if (y!=k)
{
int z=fa[y];
if (ch[z][0]==y^ch[y][0]==x) rot(x,k);
else rot(y,k);
}
rot(x,k);
}
} int pre(int x)
{
if (ch[x][0])
{
x=ch[x][0];
while (ch[x][1]) x=ch[x][1];
return x;
}
while (ch[fa[x]][0]==x) x=fa[x]; x=fa[x];
return x;
} int nxt(int x)
{
if (ch[x][1])
{
x=ch[x][1];
while (ch[x][0]) x=ch[x][0];
return x;
}
while (ch[fa[x]][1]==x) x=fa[x]; x=fa[x];
return x;
} int main()
{
scanf("%d",&n);
F(i,2,n)
{
int u; scanf("%d",&u);
v[u].push_back(i);
}
sta[++top]=0;dfs(1);sta[++top]=0;
F(i,1,n) scanf("%d",&w[i]);
rt=build(1,top,0);
scanf("%d",&m);
F(i,1,m)
{
scanf("%s",opt);
int x,y,tmp,L,R;
switch(opt[0])
{
case 'Q':
scanf("%d",&x);
splay(pre(pos[1][0]),rt);
splay(nxt(pos[x][0]),ch[rt][1]);
printf("%lld\n",sum[ch[ch[rt][1]][0]]);
break;
case 'C':
scanf("%d%d",&x,&y);
splay(pre(pos[x][0]),rt);
splay(nxt(pos[x][1]),ch[rt][1]);
tmp=ch[ch[rt][1]][0];
fa[tmp]=0; ch[ch[rt][1]][0]=0;
update(ch[rt][1]); update(rt);
L=pos[y][0];R=pos[y][0]+1;
splay(pos[y][0],rt);
splay(nxt(pos[y][0]),ch[rt][1]);
ch[ch[rt][1]][0]=tmp;
fa[tmp]=ch[rt][1];
update(ch[rt][1]); update(rt);
break;
case 'F':
scanf("%d%d",&x,&y);
splay(pre(pos[x][0]),rt);
splay(nxt(pos[x][1]),ch[rt][1]);
tag[ch[ch[rt][1]][0]]+=y; tmp=ch[ch[rt][1]][0];
val[tmp]+=y*pn[tmp];
sum[tmp]+=1LL*(siz[tmp][1]-siz[tmp][0])*y;
break;
}
}
}

  

BZOJ 3786 星系探索 ——Splay的更多相关文章

  1. BZOJ 3786 星系探索 (splay+dfs序)

    题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...

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

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

  3. bzoj 3786 星系探索 dfs+splay

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

  4. BZOJ 3786 星系探索

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

  5. BZOJ 3786: 星系探索 ETT

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

  6. BZOJ 3786: 星系探索 [伪ETT]

    传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...

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

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

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

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

  9. bzoj3786星系探索 splay

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

随机推荐

  1. Unity四元素运用之风向标跟随箭头

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class WindVane ...

  2. [学习总结] python语言学习总结 (三)

    函数闭包 定义 延伸了作用域的函数(能访问定义体之外定义的非全局变量 作用 共享变量的时候避免使用了不安全的全局变量 允许将函数与某些数据关联起来,类似于简化版面向对象编程 相同代码每次生成的闭包,其 ...

  3. Spark集锦

    1 Spark官网  http://spark.apache.org/ 2 Spark书籍 http://down.51cto.com/tag-spark%E4%B9%A6%E7%B1%8D.html

  4. openstack rocky kolla docker

    https://docs.openstack.org/kolla-ansible/latest/user/quickstart.html

  5. 《剑指offer》39题—数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  6. php的字符转换 & php登入注册界面设计以及源码 & 分离公共部分

    我们在编写的时候总是会出现乱码 https://www.cnblogs.com/mafeng/p/5827215.html php登入注册界面设计以及源码 https://blog.csdn.net/ ...

  7. cocos2dx通过ndk编译c++库

    ndk编译c++库,然后通过jni调用实现重要代码封装,是安卓应用中最常用的技术,一方面可以将重要的代码实现隐藏,防止泄漏,也可以提高打包速度. ndk里面的sample文件夹中有很多实用的例子,其中 ...

  8. 简单的cocos2dx笔试题

    1.参数传递有几种方式?值传递.指针传递.引用传递 2.指针和引用有什么分别:如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗? 1.指针是一个变量,存储一个地址,指向内存的一个存储单元: ...

  9. Neural Style论文笔记+源码解析

    引言 前面在Ubuntu16.04+GTX1080配置TensorFlow并实现图像风格转换中介绍了TensorFlow的配置过程,以及运用TensorFlow实现图像风格转换,主要是使用了文章A N ...

  10. NOIP2016——一个逗号引发的血案

    今年江西省报名人数一下子增起来了 隔壁中学来了80+人(虽然都是来给我们垫底的...临时被老师抓来上战场 总之我们赛区参赛人数总算多起来了(起码没再减50%...连续4年减50%真不是随便说说的... ...