BZOJ 3786: 星系探索 欧拉游览树
一个叫 Euler-Tour-Tree 的数据结构,说白了就是用 Splay_Tree 维护欧拉序
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdio>
using namespace std;
void setIO(string a){
freopen((a+".in").c_str(),"r",stdin);
freopen((a+".out").c_str(),"w",stdout);
}
#define maxn 300000
#define ll long long
int euler[maxn], w[maxn], cnt=1;
int head[maxn],to[maxn],nex[maxn],edges,root;
ll sumv[maxn], val[maxn], lazy[maxn];
void addedge(int u,int v){
nex[++edges]=head[u],head[u]=edges,to[edges]=v;
}
void dfs(int u){
euler[++cnt]=u*2, val[u*2]=w[u];
for(int v=head[u];v;v=nex[v])
dfs(to[v]);
euler[++cnt]=u*2+1, val[u*2+1]=-w[u];
}
struct Splay_Tree{
int f[maxn],ch[maxn][2],sta[maxn],siz[maxn];
int rson(int x)
{
return ch[x][1];
}
int lson(int x)
{
return ch[x][0];
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void update(int x,int c)
{
val[x]+=(x%2==0?1:-1)*c;
lazy[x]+=c;
sumv[x]+=siz[x]*c;
}
void pushup(int x)
{
sumv[x]=sumv[lson(x)]+sumv[rson(x)]+val[x];
siz[x]=siz[lson(x)]+siz[rson(x)];
siz[x]+=(x>=200099 ? 0: (x%2==0?1:-1));
}
void pushdown(int x)
{
if(lazy[x]) update(lson(x),lazy[x]), update(rson(x),lazy[x]),lazy[x]=0;
}
int pre(int x)
{
splay(x,root);
x=lson(root);
while(rson(x)) x=rson(x);
return x;
}
int las(int x)
{
splay(x,root);
x=rson(root);
while(lson(x)) x=lson(x);
return x;
}
void build(int l,int r,int &o,int fa)
{
if(l>r)return;
int mid=(l+r)>>1;
o=euler[mid], f[o]=fa;
build(l,mid-1,ch[o][0],o);
build(mid+1,r,ch[o][1],o);
pushup(o);
}
void rotate(int x)
{
int old=f[x], oldf=f[old], which=get(x);
ch[old][which]=ch[x][which^1], f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=oldf;
if(oldf) ch[oldf][ch[oldf][1]==old]=x;
pushup(old),pushup(x);
}
void splay(int x,int &tar)
{
int v=0,u=x,a=f[tar];
while(u!=a) sta[++v]=u,u=f[u];
while(v) pushdown(sta[v--]);
for(int fa;(fa=f[x])!=a;rotate(x))
if(f[fa]!=a) rotate(get(fa)==get(x)?fa:x);
tar=x;
}
void opt1(int a)
{
int x=las(a*2);
splay(200100,root),splay(x,ch[root][1]);
printf("%lld\n",sumv[ch[ch[root][1]][0]]);
}
void opt2(int a,int b)
{
int x=pre(a*2),y=las(a*2+1),tmp;
splay(x,root),splay(y,ch[root][1]);
tmp=ch[ch[root][1]][0], ch[ch[root][1]][0]=f[tmp]=0;
pushup(ch[root][1]), pushup(root);
x=las(b*2);
splay(b*2,root), splay(x,ch[root][1]);
ch[ch[root][1]][0]=tmp,f[tmp]=ch[root][1];
pushup(ch[root][1]),pushup(root);
}
void opt3(int a,int b)
{
int x=pre(a*2),y=las(a*2+1);
splay(x,root),splay(y,ch[root][1]);
update(ch[ch[root][1]][0],b);
pushup(ch[root][1]),pushup(root);
}
}tree;
int main(){
//setIO("input");
int n,x,m;
scanf("%d",&n);
for(int i=2;i<=n;++i)
scanf("%d",&x),addedge(x,i);
for(int i=1;i<=n;++i) scanf("%d",&w[i]);
dfs(1);
euler[1]=200100, euler[++cnt]=200101;
tree.build(1,cnt,root,0);
scanf("%d",&m);
while(m--)
{
char opt[10];
int a,b;
scanf("%s",opt);
if(opt[0]=='Q')
{
scanf("%d",&a);
tree.opt1(a);
}
if(opt[0]=='C')
{
scanf("%d%d",&a,&b);
tree.opt2(a,b);
}
if(opt[0]=='F')
{
scanf("%d%d",&a,&b);
tree.opt3(a,b);
}
}
return 0;
}
BZOJ 3786: 星系探索 欧拉游览树的更多相关文章
- 数据结构&图论:欧拉游览树
ETT可以称为欧拉游览树,它是一种和欧拉序有关的动态树(LCT是解决动态树问题的一种方案,这是另一种) dfs序和欧拉序是把树问题转化到区间问题上然后再用数据结构去维护的利器 通过借助这两种形式能够完 ...
- BZOJ 3786: 星系探索 解题报告
3786: 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅 ...
- BZOJ 3786 星系探索
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3786: 星系探索 [伪ETT]
传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...
- bzoj 3786 星系探索 dfs+splay
[BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...
- BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现 ...
- BZOJ 3786: 星系探索 ETT
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3786 星系探索 ——Splay
子树可以移动,唔. 还是用Splay维护DFS序即可. 子树的话直接截取出来就好了. 然后求前驱后继可能麻烦一些. 添加两个虚拟节点会比较好写. #include <map> #inclu ...
- BZOJ 2818 Gcd 线性欧拉
题意:链接 方法:线性欧拉 解析: 首先列一下表达式 gcd(x,y)=z(z是素数而且x,y<=n). 然后我们能够得到什么呢? gcd(x/z,y/z)=1; 最好还是令y>=x 则能 ...
随机推荐
- m_Orchestrate learning system---二十七、修改时如何快速找到作用位置
m_Orchestrate learning system---二十七.修改时如何快速找到作用位置 一.总结 一句话总结:找人,找起作用的位置真的重要,找到就事半功倍了 加载页面的时候观察在f12的e ...
- Pcap 数据报解析
最近看了一下网络的书,信息系统也有实验任务,所以就学习了一下pcap包的解析. 主要是对内部以太网帧头,ip头部,tcp头部或者udp头部的解析.我因为用访问google.cn作为的样例,没有udp包 ...
- python 3.x 学习笔记9 (面向对象)
1.面向对象 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. 2.类(class): 一个类即是对一类拥有相同属性的对象的抽象.蓝图.原型.在类中定义了这些对象的都 ...
- 【原创】关于class.forname
连接数据库前都要调用一下class.forname("driverName");然后使用DriverMnager获取连接,这是为什么呢? 首先jdbc标准要求,每个驱动必须向Dri ...
- 【原创】TimeSten安装与配置
1.安装TimeSten 2.安装时要指定TNS_ADMIN_LOCATION,即tnsnames.ora的路径,因为tt会根据这个连接Oracle.C:\TimesTen\tt1122_32\net ...
- hiho150周 - 动态规划*
题目链接 一个n*m的迷宫由‘.’和'b'组成,从(1,1)走到(n,m),只能向右或者向下走,但遇到‘b’时才能改变方向,开始时方向向右. 问到达(n,m)至少改变几个位置上的值 /******** ...
- c# 02-18 值类型 引用类型 字符串的不可变性 字符串的处理方法
1值类型 直接把值存在栈中 栈的特点是后进先出 int double decimal char struct enum bool 2 引用类型 把值存在堆中,把地址存在栈中: string 自定义的类 ...
- stm8s103 EEPROM烧程序时能否保留
EEPROM的参数需要再烧录程序时保留,做试验测试是否能够保留 1.在ST Visual Develop中硬件仿真手动修改EEPROM的值. 2.在ST Visual Programmer中读取EEP ...
- 手把手教你如何新建scrapy爬虫框架的第一个项目(下)
前几天小编带大家学会了如何在Scrapy框架下创建属于自己的第一个爬虫项目(上),今天我们进一步深入的了解Scrapy爬虫项目创建,这里以伯乐在线网站的所有文章页为例进行说明. 在我们创建好Scrap ...
- 改造vue-quill-editor: 结合element-ui上传图片到服务器
前排提示:现在可以直接使用封装好的插件vue-quill-editor-upload 需求概述 vue-quill-editor是我们再使用vue框架的时候常用的一个富文本编辑器,在进行富文本编辑的时 ...