BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)
Description
强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这个大树实际上是一个带权树。每个时刻它会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + Rj,其中 dist(i, j)表示在这个树上从 i 到 j 的唯一路径上所有边的边权和。强强和萌萌很好奇每次新长出一个叶子节点之后,这个树上总共有几对朋友。
我们假定这个树一开始为空,节点按照加入的顺序从 1开始编号。由于强强非常好奇, 你必须在他每次出现新节点后马上给出总共的朋友对数,不能拖延哦。
Input
共有 n + 2 行。
第一行包含一个正整数,表示测试点编号。
第二行包含一个正整数 n ,表示总共要加入的节点数。
我们令加入节点前的总共朋友对数是 last_ans,在一开始时它的值为0。
接下来 n 行中第 i 行有三个数 ai, bi, ri,表示节点 i 的父节点的编号为 ai xor (last_ans mod 10^9) (其中xor 表示异或,mod 表示取余,数据保证这样操作后得到的结果介于 1到i – 1之间),与父节点之间的边权为 ci,节点 i 上小精灵的感受能力值为ri。
注意 a1 = c1 = 0,表示 1 号点是根节点,对于 i > 1,父节点的编号至少为1。
Output
包含 n 行,每行输出1 个整数, 表示加入第 i 个点之后,树上有几对朋友。
Sample Input
5
0 0 6
1 2 4
0 9 4
0 5 5
0 2 4
Sample Output
1
2
4
7
解题思路:
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define lll tr[spc].ls
#define rrr tr[spc].rs
typedef long long lnt;
const double alpha=0.77;
struct pnt{
int hd;
int F;
int T;
int dp;
int val;
int wgt;
int wgt_;
int fa[];
int root;
int root_;
lnt dis;
bool vis;
}p[];
struct ent{
int twd;
int lst;
int vls;
}e[];
struct trnt{
int ls;
int rs;
int val;
int wgt;
int rnd;
}tr[],BLANK_TRNT;
int siz;
int top;
int cnt;
int tot;
int tms;
int root;
int maxval;
int n,test_no;
lnt lastans;
int bin[];
void del(int &spc)
{
if(!spc)return ;
bin[++top]=spc;
spc=;
return ;
}
int newp(void)
{
if(top)
{
int spc=bin[top--];
if(lll)bin[++top]=lll;
if(rrr)bin[++top]=rrr;
return spc;
}
return ++siz;
}
int apply(int v)
{
int spc=newp();
tr[spc]=BLANK_TRNT;
tr[spc].val=v;
tr[spc].rnd=rand();
tr[spc].wgt=;
return spc;
}
void pushup(int spc)
{
tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+;
return ;
}
void lturn(int &spc)
{
int tmp=lll;
lll=tr[tmp].rs;
tr[tmp].rs=spc;
pushup(spc);
pushup(tmp);
spc=tmp;
return ;
}
void rturn(int &spc)
{
int tmp=rrr;
rrr=tr[tmp].ls;
tr[tmp].ls=spc;
pushup(spc);
pushup(tmp);
spc=tmp;
}
void insert(int &spc,int v)
{
if(!spc)
{
spc=apply(v);
return ;
}
if(tr[spc].val<v)
{
insert(rrr,v);
if(tr[rrr].rnd<tr[spc].rnd)rturn(spc);
}else{
insert(lll,v);
if(tr[lll].rnd<tr[spc].rnd)lturn(spc);
}
pushup(spc);
return ;
}
int rank(int spc,int v)
{
int ans=;
while(spc)
{
if(tr[spc].val<v)
{
ans+=tr[lll].wgt+;
spc=rrr;
}else spc=lll;
}
return ans;
}
//------------^Treap
void ade(int f,int t,int v)
{
if(!f||!t)return ;
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void decode(int &tmp_a)
{
tmp_a^=(lastans%);
return ;
}
int lca(int x,int y)
{
if(p[x].dp<p[y].dp)std::swap(x,y);
for(int i=;i>=;i--)
if(p[p[x].fa[i]].dp>=p[y].dp)
x=p[x].fa[i];
if(x==y)return x;
for(int i=;i>=;i--)
{
if(p[x].fa[i]!=p[y].fa[i])
{
x=p[x].fa[i];
y=p[y].fa[i];
}
}
return p[x].fa[];
}
lnt dis(int x,int y)
{
return p[x].dis+p[y].dis-p[lca(x,y)].dis*;
}
void kill(int x,int f,int t)
{
tot++;
p[x].wgt_=;
p[x].T=tms;
p[x].vis=false;
del(p[x].root);
del(p[x].root_);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f||p[to].wgt_>t)continue;
kill(to,x,t);
}
return ;
}
void grc_dfs(int x,int f)
{
p[x].wgt=;
int maxs=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f||p[to].vis)continue;
grc_dfs(to,x);
p[x].wgt+=p[to].wgt;
maxs=std::max(maxs,p[to].wgt);
}
maxs=std::max(maxs,tot-p[x].wgt);
if(maxs<maxval)
{
root=x;
maxval=maxs;
}
return ;
}
void bin_dfs(int x,int F)
{
p[x].F=F;
p[x].vis=true;
int tmpv=tot;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].vis)continue;
if(p[x].wgt>p[to].wgt)tot=p[to].wgt;
else tot=tmpv-p[x].wgt;
root=;
maxval=0x3f3f3f3f;
grc_dfs(to,to);
bin_dfs(root,x);
}
return ;
}
void relive(int x,int f,int F)
{
for(int i=x;i!=F;i=p[i].F)
{
p[i].wgt_++;
insert(p[i].root,dis(x,i)-p[x].val);
if(!p[i].F)break;
insert(p[i].root_,dis(p[i].F,x)-p[x].val);
}
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].T!=tms||to==f)continue;
relive(to,x,F);
}
return ;
}
void rebuild(int x)
{
tms++;
int F=p[x].F;
tot=;
root=;
maxval=0x3f3f3f3f;
kill(x,x,p[x].wgt_);
grc_dfs(x,x);
bin_dfs(root,F);
relive(x,x,F);
return ;
}
void T_insert(int x)
{
int plc=;
p[x].wgt_=;
insert(p[x].root,-p[x].val);
for(int i=x;p[i].F;i=p[i].F)
{
insert(p[p[i].F].root,dis(p[i].F,x)-p[x].val);
insert(p[i].root_,dis(p[i].F,x)-p[x].val);
p[p[i].F].wgt_++;
if(1.00*p[i].wgt_>alpha*p[p[i].F].wgt_)plc=p[i].F;
}
if(plc)rebuild(plc);
return ;
}
lnt T_query(int x)
{
lnt ans=rank(p[x].root,p[x].val+)-;
for(int i=x;p[i].F;i=p[i].F)
{
ans+=rank(p[p[i].F].root,p[x].val-dis(p[i].F,x)+);
ans-=rank(p[i].root_,p[x].val-dis(p[i].F,x)+);
}
return ans;
}
int main()
{
scanf("%d",&test_no);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
p[i].vis=true;
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
decode(a);
p[i].F=a;
p[i].val=c;
p[i].dp=p[a].dp+;
p[i].dis=p[a].dis+b;
if(i!=)p[i].fa[]=a;
else p[i].fa[]=;
for(int j=;j<=;j++)p[i].fa[j]=p[p[i].fa[j-]].fa[j-];
ade(i,a,b);ade(a,i,b);
T_insert(i);
lastans+=T_query(i);
printf("%lld\n",lastans);
}
return ;
}
BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)的更多相关文章
- bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400
3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec Memory Limit: 512 MBSubmit: 159 Solved: 40[Submit][Status] ...
- BZOJ 3435 / Luogu 3920 [WC2014]紫荆花之恋 (替罪羊树 动态点分治 套 Treap)
题意 略 分析 引用PoPoQQQ的话 吾辈有生之年终于把这道题切了...QAQ (蒟蒻狂笑) Orz PoPoQQQ,我又抄PoPoQQQ的题解了 - 突然发现有旋Treap没那么难写 学习了一波C ...
- BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)
传送门(权限) 传送门(非权限) 题解 我终终终终终终于做出来啦!!! 作为一个没有学过替罪羊树的蒟蒻现场学了一下替罪羊树,作为一个平衡树都写数组版本的看着大佬的指针题解无语只能硬去理解然后照着抄了一 ...
- bzoj3435 [Wc2014]紫荆花之恋
如果这棵树不变的话,就是一个裸的点分树套平衡树,式子也很好推$di+dj<=ri+rj$,$ri-di>=dj-rj$ 平衡树维护$dj-rj$,然后查$ri-di$的$rank$即可. ...
- 【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT
[BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从 ...
- BZOJ 3435: [Wc2014]紫荆花之恋
二次联通门 : BZOJ 3435: [Wc2014]紫荆花之恋 二次联通门 : luogu P3920 [WC2014]紫荆花之恋 /* luogu P3920 [WC2014]紫荆花之恋 怀疑人生 ...
- 【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- [WC2014]紫荆花之恋(动态点分治+替罪羊思想)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
随机推荐
- Qt之QSS(动态属性)
简述 QSS可以定制应用程序的外观,无需关注Qt样式背后的魔力.从非常轻微到极其复杂的调整,样式表都可以做到.对于一个完全定制和独特的用户体验,QtQuick和QGraphicsView是更好的选择. ...
- Woody的Python学习笔记4
Python模块 Import语句 想要使用Python源文件,仅仅须要在还有一个源文件中运行import语句.语法例如以下: import module1 当解释器遇到import语句.假设模块在当 ...
- mysql-联结
一.联结 联结是利用SQL的select能执行的最重要的操作. 1.关系表:假如有一个包含产品目录的数据库表,其中每个类别的物品占一行.对于每种物品要求存储的信息包括产品描述和价格,以及生产该产品的供 ...
- tomcat和nginx相互结合的优化调整
在工作中遇到这样的情况 Tomcat为后台 nginx为反向代理 需要往后台导入数据,由于处理时间过长,导致访问时出现504和500 通过修改tomcat中maxParameterCount=&qu ...
- nfs共享文件服务搭建
网络文件共享服务器192.10.19.132yum install -y nfs-utils 在exports文件中添加的从机范围vim /etc/exports/home/nfs/ 192.10.1 ...
- [poj 2773] Happy 2006 解题报告 (二分答案+容斥原理)
题目链接:http://poj.org/problem?id=2773 题目大意: 给出两个数m,k,要求求出从1开始与m互质的第k个数 题解: #include<algorithm> # ...
- storm集群安装配置
1.上传解压 2.进入到storm的conf目录 接上图 启动三台节点的zookeeper集群 启动和查看 Storm 在 nimbus.host 所属的机器上启动 nimbus 服务和 logvi ...
- 虚拟主机TOMCAT配置
在tomcat中添加虚拟主机: 编辑"tomcat\conf\server.xml",在"<Engine></Engine>"元素中新加 ...
- SQL--去除字符串空格、截取字符串
1
- Linux 文件系统详解
作者: Paul Brown 译者: LCTT amwps290 这篇教程将帮你快速了解 Linux 文件系统. 早在 1996 年,在真正理解文件系统的结构之前,我就学会了如何在我崭新的 Linux ...