[BZOJ3786]星系探索(伪ETT)
3786: 星系探索
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 1638 Solved: 506
[Submit][Status][Discuss]Description
物理学家小C的研究正遇到某个瓶颈。
他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。
我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.
对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.
每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。
但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。
有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。
现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。
Input
第一行一个整数n,表示星系的星球数。
接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。
接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.
接下来一行一个整数m,表示事件的总数。
事件分为以下三种类型。
(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.
(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.
(3)"F pi qi"表示星球pi能量激发,常数为qi.
Output
对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。
Sample Input
3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2Sample Output
9
15
25HINT
n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保证操作合法。注意w_i>=0
Source
ETT三题:
[BZOJ4825 HNOI2017 单旋]
[BZOJ3729 Gty的游戏]
[BZOJ3785]星系探索
Euler Tour Tree(欧拉游览树)是一种可以支持比LCT更多的操作的数据结构,但其无论从功能还是复杂度方面都远不如TopTree和Self Adjust Tree好。
真正的ETT的操作有很多,但一般只需要用到伪ETT,实际上就是splay维护DFS序。
以此题为例,如果没有子树修改,就是LCT模板,如果没有在线Link-Cut,就是DFS序+线段树模板。同时有的时候就需要一种支持在线DFS区间修改的数据结构,且支持区间平移操作,splay无疑是最好的选择。
具体做法是维护DFS括号序列(也就是欧拉序),进栈值为v,出栈值为-v,所以u到v的路径上的所有数之和就是DFS序上L[u]到L[v]的数之和了(所以这题可以支持查询任意树上路径和而不只是某个点到根的路径和),树上莫队应该也是类似的思想。
那么C操作如何支持呢?考虑到一个子树移到另一个位置后,整棵树的DFS序正是原DFS序中L[u]到R[u]的区间平移到新的位置,区间平移操作直接用splay支持即可,复杂度不变。
于是这题就1h就写完且答案正确了,但是BZOJ上无限TLE,一直以为是哪里死循环了不停查错,幸亏发现良心出题人在网上放出了数据才知道是常数问题。发现各种常数优化都无济于事,最后才知道:把splay上的信息存在一个struct里常数会缩小将近一倍!究其原因应该是访问同一个节点的不同信息的时候要在好几个数组里查找,大幅增加了寻址时间。看来以后splay等数据结构要考虑全部换成结构体写法了。
那就正好趁这个机会总结一下各种卡常技巧:
1. register是最好用的(但有时没有效果),非递归函数参数也可以用。
2. 多维数组从前往后大小依次递增效果最好。相应地,寻址时在高维的循环变量应位于外层循环(如矩乘)。
3. 数组开2^k+1据说很有用,但好像从来没有收到良好效果。
4. 多次用到的define换成函数会更快,多次用到的数组元素应用temp存下。
5. 排序不应使用cmp函数,应在结构体内部重载<运算符。
6. 多用struct好像可以加快一些访问的速度。
7. 能用位运算的不要取模。循环展开大概4位或8位。
8. 根据情况多加循环中止判断语句,这个剩至可以降低理论复杂度。
#include<cstdio>
#include<algorithm>
#define ls t[x].ch[0]
#define rs t[x].ch[1]
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=;
int cnt,x,y,n,Q,rt,tim,L[N],R[N],val[N],a[N],to[N<<],lst[N<<],h[N];
struct T{ int sl,sr,v,fa,type,ch[]; ll sum,tag; }t[N];
char op;
void add(int u,int v){ to[++cnt]=v; lst[cnt]=h[u]; h[u]=cnt; } void upd(int x){
t[x].sum=t[ls].sum+t[rs].sum+t[x].v;
t[x].sl=t[ls].sl+t[rs].sl+(t[x].type==);
t[x].sr=t[ls].sr+t[rs].sr+(t[x].type==-);
} void put(int x,int k){ t[x].sum+=1ll*k*(t[x].sl-t[x].sr); t[x].v+=k*t[x].type; t[x].tag+=k; }
void push(int x){
if (t[x].tag){
if (ls) put(ls,t[x].tag);
if (rs) put(rs,t[x].tag);
t[x].tag=;
}
}
void mdf(int x){ if (t[x].fa) mdf(t[x].fa); push(x); } void rot(int &rt,int x){
int y=t[x].fa,z=t[y].fa,w=t[y].ch[]==x;
if (y==rt) rt=x; else t[z].ch[t[z].ch[]==y]=x;
t[x].fa=z; t[y].fa=x; t[t[x].ch[w^]].fa=y;
t[y].ch[w]=t[x].ch[w^]; t[x].ch[w^]=y; upd(y);
} void splay(int &rt,int x){
mdf(x);
while (x!=rt){
int y=t[x].fa,z=t[y].fa;
if (y!=rt) rot(rt,(t[z].ch[]==y)^(t[y].ch[]==x) ? x : y);
rot(rt,x);
}
upd(x);
} void dfs(int x){
L[x]=++tim; val[tim]=x;
for (int i=h[x]; i; i=lst[i]) dfs(to[i]);
R[x]=++tim; val[tim]=-x;
} void build(int &x,int L,int R,int f){
int mid=(L+R)>>; x=mid; t[x].fa=f;
if (val[x]>) t[x].type=,t[x].v=a[val[x]]; else t[x].type=-,t[x].v=-a[-val[x]];
if (L<mid) build(ls,L,mid-,x);
if (mid<R) build(rs,mid+,R,x);
upd(x);
} int pre(int x){ x=ls; while (rs) x=rs; return x; }
int nxt(int x){ x=rs; while (ls) x=ls; return x; } void split(int &l,int &r){
splay(rt,l); l=pre(l);
splay(rt,r); r=nxt(r);
splay(rt,l); splay(t[l].ch[],r);
} ll que(int x){ int l=L[],r=L[x]; split(l,r); return t[t[r].ch[]].sum; } void plus(int x,int k){ int l=L[x],r=R[x]; split(l,r); put(t[r].ch[],k); } void change(int x,int f){
int l=L[x],r=R[x]; split(l,r);
int q=t[r].ch[]; t[r].ch[]=t[q].fa=; upd(r); upd(l);
int p=L[f]; splay(rt,p);
int s=nxt(p); splay(t[p].ch[],s);
t[s].ch[]=q; t[q].fa=s; upd(s); upd(p);
} int main(){
freopen("bzoj3786.in","r",stdin);
freopen("bzoj3786.out","w",stdout);
scanf("%d",&n);
rep(i,,n) scanf("%d",&x),add(x,i);
rep(i,,n) scanf("%d",&a[i]);
tim=; dfs(); build(rt,,tim+,);
for (scanf("%d",&Q); Q--; ){
scanf(" %c",&op); scanf("%d",&x);
if (op=='Q') printf("%lld\n",que(x));
else if (op=='C') scanf("%d",&y),change(x,y); else scanf("%d",&y),plus(x,y);
}
return ;
}
[BZOJ3786]星系探索(伪ETT)的更多相关文章
- BZOJ 3786: 星系探索 [伪ETT]
传送门 数据,标程 题意: 一颗有根树,支持询问点到根路径权值和,子树加,换父亲 欧拉序列怎么求路径权值和? 一个点的权值只会给自己的子树中的点贡献,入栈权值正出栈权值负,求前缀和就行了! 和上题一样 ...
- [BZOJ3786]星系探索
[BZOJ3786]星系探索 试题描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个 ...
- BZOJ3786 星系探索 【Splay维护dfs序】*
BZOJ3786 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均 ...
- BZOJ3786: 星系探索(伪ETT)
题面 传送门 题解 坑啊--我好像把\(Splay\)的东西全忘光了-- \(ETT\)(\(Euler\ Tour\ Tree\))是一种可以资瓷比\(LCT\)更多功能的数据结构,然而不管是功能还 ...
- [BZOJ3786] 星系探索(括号序列+Splay)
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 2191 Solved: 644[Submit][Status][Discuss ...
- bzoj3786星系探索 splay
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1314 Solved: 425[Submit][Status][Discuss ...
- BZOJ3786星系探索——非旋转treap(平衡树动态维护dfs序)
题目描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. ...
- BZOJ3786:星系探索(Splay,括号序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
随机推荐
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
这道题看题意是在求一个二维最小瓶颈路,唯一可行方案就是枚举一维在这一维满足的条件下使另一维最小,那么我们就把第一维排序利用A小的边在A大的情况下仍成立来动态加边维护最小生成树. #include &l ...
- 第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 A
Problem 1603 - Minimum Sum Time Limit: 2000MS Memory Limit: 65536KB Total Submit: 564 Accepted: ...
- SICAU-OJ: A|B
A|B 题意: 给出一个整数n(1<=n<=10100),求Σd(d满足d可以整除n),同时保证不存在x^2有x^2可以整除n. 另外,n的质因子满足小于等于1000. 题解: 这题是我第 ...
- Bash 实例,第一部分
您可能要问:为什么要学习 Bash 编程?好,以下是几条令人信服的理由: 已经在运行它 如果查看一下,可能会发现:您现在正在运行 bash.因为 bash 是标准 Linux shell,并用于各种目 ...
- Android推送使用--文章集锦
Android之基于百度云推送IM Android实现推送方式解决方案 Android消息推送(一)--AndroidPn(XMPP协议)Demo版到正式上线 采用XMPP协议实现Android推送 ...
- java属性为什么没多态,而是方法多态
定义 java多肽的特性:方法具有多态性,属性却没有. 准备 基类: 子类: 测试类: 结果: 分析如下 父类 a=new 子类,实际对象时子类.由于向上转型,我们可以用父类在编译期间代替子类,使得编 ...
- Spring - IoC(3): Bean 实例的创建方式
创建一个 Bean 实例对象的方法通常有如下方式: 调用构造器创建 Bean 实例 调用静态工厂方法创建 Bean 实例 调用实例工厂方法创建 Bean 实例 使用构造器创建 Bean 实例 XML ...
- SuSE Linux10.1 网络设置以及和主机通信
SuSE Linux10.1 网络设置以及和主机通信 http://www.cnblogs.com/kevintian/articles/1086994.html 在VMWare上安装好SuSE之后, ...
- Chubby lock service for distributed system
Chubby lock service在分布式系统中的应用 Chubby lock service在分布式系统中提供粗粒度的锁服务, 以及可靠的存储. 相比高性能, 设计的重点在于高可靠性和高可用性. ...
- ubuntu16.04下fcitx无法在QT Creator输入中文解决办法
我的博客新地址:www.liuquanhao.com ------------------------------------------------------ Qt creator无法用fcitx ...