BZOJ3786: 星系探索 Splay+DFS序
题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲。
分析:
看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊...
那么,考虑更换一个点的父亲这个操作很有意思,也就是说明,整个树的结构不会有什么大的变化,只是某个节点的父亲变了,那么也就是相当于在DFS序上顺序的变化,那么我们就可以考虑化简它的树结构,从而在序列上解决。
而对于这道题,DFS序能解决,但需要维护更多信息,而且乘法的次数多了很多次,没试,但是应该过不去。我们可以换一种序列,也就是入栈出栈序,这样就可以完美解决了。
我们动态的维护四个信息,Splay Tree该节点的子树大小,该节点的子树和,和子树正号数量-符号数量符号,Lazy标记。之后每次PushDown的时候用Lazy*num来更新sum。其他的照常。
关键是每次查询的时候,因为我们不论怎么改变这个序列,有一点从来没有变,就是对应的树上节点在Splay Tree上的节点标号,那么每次只需要找到前驱后继即可,而找到前驱后继显然最好还是用Query_rank和Query_x分别表示找到对应节点的排名和对应排名的节点编号,非递归,记得在Query_x的时候PushDown就可以了!
之后Rank1什么的,就不用在意了...毕竟Splay的常数...大家知道就好...
不过我已经尽力了...最快优化到33s,不知道还有没有其他优化...
附上代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;
#define N 200005
#define ll long long
#define ls ch[rt][0]
#define rs ch[rt][1]
#define get(rt) (ch[f[rt]][0]!=rt)
#define PushUp(rt) num[rt]=num[ch[rt][0]]+num[ch[rt][1]]+flag[rt],sum[rt]=sum[ch[rt][0]]+sum[ch[rt][1]]+val[rt]*flag[rt],siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
__attribute__((optimize("-O3")))int rd() {
register int x=0;register char ch=nc();
while(ch<'0'||ch>'9') ch=nc();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=nc();
return x;
}
struct node{int to,next;}e[N];
int head[N],f[N],num[N],siz[N],cnt,flag[N],n,rot,ch[N][2],tmp,tims,a[N],idx[N],p[N];
ll sum[N];int add[N],val[N];
void add1(int x,int y){e[cnt]=(node){y,head[x]},head[x]=cnt++;}
void dfs(int x)
{
idx[++tims]=x;p[x]=tims;
for(int i=head[x];i!=-1;i=e[i].next)dfs(e[i].to);
idx[++tims]=x+n;p[x+n]=tims;
}
void PushDown(int rt)
{
if(add[rt])
{
sum[ls]+=(long long)(add[rt])*num[ls],val[ls]+=add[rt],add[ls]+=add[rt];
sum[rs]+=(long long)(add[rt])*num[rs],val[rs]+=add[rt],add[rs]+=add[rt];
add[rt]=0;
}
}
void rotate(int rt)
{
int x=f[rt],y=f[x],k=get(rt);
if(x!=rot)ch[y][ch[y][0]!=x]=rt;else rot=rt;
ch[x][k]=ch[rt][!k];f[ch[x][k]]=x;
ch[rt][!k]=x;f[x]=rt;f[rt]=y;
PushUp(x);PushUp(rt);
}
void Splay(int rt,int y)
{
register int fa;
for(;(fa=f[rt])!=y;rotate(rt))
if(f[fa]!=y)
rotate((get(fa)==get(rt))?fa:rt);
}
void build(int fa,int l,int r)
{
if(l>r)return;int m=(l+r)>>1;
ch[fa][m>fa]=m;f[m]=fa;siz[m]=1;//printf("%d %d %d\n",idx[m],m,val[m]);
build(m,l,m-1);build(m,m+1,r);PushUp(m);
}
int query_k(int rt)
{
int ret=0;
while(rt)
{
// PushDown(rt);
// printf("%d %d %d\n",x,idx[rt],ret);
if(rt==rot)ret+=siz[ls]+1;
else if(get(rt))ret+=siz[ls]+1;
else ret-=siz[rs]+1;
rt=f[rt];
}
return ret;
}
int find(int x)
{
register int rt=rot;
while(1)
{
PushDown(rt);
if(x<=siz[ls])rt=ls;
else
{
x-=siz[ls]+1;
if(!x)return rt;
rt=rs;
}
}
}
void cut(int x)
{
int rt=find(query_k(p[x+n])+1);x=find(query_k(p[x])-1);
Splay(x,0);Splay(rt,rot);tmp=ls;
ls=f[ls]=0;PushUp(rt);PushUp(x);
}
void link(int x)
{
int rt=find(query_k(p[x])+1);x=find(query_k(p[x]));
Splay(x,0);Splay(rt,rot);
// printf("%d %d\n",x,rt);
ls=tmp;f[tmp]=rt;PushUp(rt);PushUp(x);
}
void Update(int x,int c)
{
int rt=find(query_k(p[x+n])+1);x=find(query_k(p[x])-1);
Splay(x,0);Splay(rt,rot);
add[ls]+=c;val[ls]+=c;
}
int query(int x)
{
int rt=find(query_k(p[x])+1);x=1;
Splay(x,0);Splay(rt,rot);
printf("%lld\n",sum[ls]);
}char s[2];
int main()
{
n=rd();memset(head,-1,sizeof(head));
for(int i=2,x;i<=n;i++)add1(rd(),i);
tims=1;dfs(1);idx[++tims]=tims;idx[1]=0;
for(int i=1;i<=n;i++)a[i]=rd();
for(int i=2;i<=n*2+1;i++)
{
int x=idx[i];
if(x<=n)val[i]=a[x],flag[i]=1;
else val[i]=a[x-n],flag[i]=-1;
}
build(0,1,2*n+2);rot=n+1;int Q=rd();
while(Q--)
{
char op=nc();
while(op!='C'&&op!='Q'&&op!='F')op=nc();
int x=rd();
if(op=='Q')query(x);
else if(op=='C')
{
cut(x);
link(rd());
}else Update(x,rd());
// print();
}
return 0;
}
BZOJ3786: 星系探索 Splay+DFS序的更多相关文章
- 【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 dfs序
这道题 首先 因为他求的是当前点到根节点的路径和 我们可以将题目转换为括号序列的写法 将点拆为左括号以及右括号 左括号为正 右括号为负 这样题目就变为了求前缀和了 如果一个点是这个点的子树 那么他的左 ...
- BZOJ3786:星系探索(Splay,括号序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- bzoj3786星系探索 splay
3786: 星系探索 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1314 Solved: 425[Submit][Status][Discuss ...
- bzoj3786星系探索(splay维护dfs序)
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ3786 星系探索 【Splay维护dfs序】*
BZOJ3786 星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均 ...
- [BZOJ3786]星系探索
[BZOJ3786]星系探索 试题描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个 ...
- BZOJ_3729_Gty的游戏_博弈论+splay+dfs序
BZOJ_3729_Gty的游戏_博弈论+splay+dfs序 Description 某一天gty在与他的妹子玩游戏. 妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子 ...
随机推荐
- CSS3 鼠标划上图片放大
td img{transition: all 1s}/*鼠标划上,图片1s全部显示完成*/ td img:hover{ transform: scale(5) translateX(50%) tran ...
- CSS3关于-webkit-tap-highlight-color属性
最近在写手机端,发现了一个问题,就是javascript点击元素时,在安卓手机上会出现半透明的蓝色背景,(经百度,在苹果手机上会出现半透明的灰色背景),后来通过百度找到了解决方案,就是利用CSS3的- ...
- <Android 基础(三十一)> ObjectAnimator
简介 ObjectAnimator,是ValueAnimator的子类,支持利用目标视图的属性来实现动画效果.构造ObjectAnimator的时候,将会提取对应的参数来定义动画对象和对象属性.合适的 ...
- 学习笔记(3)——实验室集群WMS服务配置
1.启动mgt结点的tomcat服务: [root@mgt zmq]# /home/geohpc/softwares/apache-tomcat-/bin/startup.sh 关闭为 [root@m ...
- readlink 命令
在Linux中readlink命令的作用是:输出符号链接值或权威文件名(通常使用的是-f参数) 格式:readlink [选项]... 文件 参数: -f, --canonicalize 递归跟随 ...
- Forbidden Attack:7万台web服务器陷入被攻击的险境
一些受VISA HTTPS保护的站点,因为存在漏洞容易受到Forbidden攻击,有将近70,000台服务器处于危险之中. 一种被称为"Forbidden攻击"的新攻击技术揭露许多 ...
- 2016年,谁是最受欢迎的 Java EE 服务器?
[编者按]本文作者为性能监控工具 Plumbr 创始人 Nikita Salnikov-tarnovski,主要介绍2016年度最广为使用的 Java EE 容器及其排名变化情况.本文系国内 ITOM ...
- deep learning自学知识积累笔记
推荐系统的演变过程 协同过滤(英雄所见略同)思想为类似喜好的人的选择必然也类似.比如小学男生普遍喜欢打手游,中年大叔普遍喜欢射雕英雄传 随后有了SVD奇异值分解,但是SVD要求不能太稀疏,因此有了隐语 ...
- Hadoop HBase概念学习系列之META表和ROOT表(六)
在 HBase里的HRegion 里,谈过,HRegion是按照表名+开始/结束主键,即表名+主键范围来区分的.由于主键范围是连续的,所以一般用开始主键就可以表示相应的HRegion了. 不过,因为我 ...
- make报错
笔记本Ubuntu16.04环境下,进入项目的src目录下执行make操作,发现报如下错误 /bin/sh: 1: /usr/bin/libtool: not found makefile:89: r ...