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]紫荆花之恋(动态点分治+替罪羊思想)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
随机推荐
- RIP协议的配置
拓扑图: 要求: 理解RIP协议的工作原理,并通过 RIP 路由协议实现不同网络互通. 配置步骤: 1.配置好 PC 机的 IP 地址等參数. PC 0>ipconfig IP Address. ...
- Android 取得 ListView中每个Item项目的值
首先我们须要创建 ListView .这里假定我们已经创建好了而且使用SimpleAdapter设置好了adapter数据,看一下我们的adapter ArrayList<HashMap< ...
- 我是怎么利用微信做兼职月入1W的
物价上涨.导致非常多人都感觉如今的收入入不敷出,有的是迫于生活压力.有的是为了提高生活质量,等等都想好好利用业余时间来做点兼职,当然我也不例外.正好笔者在微信刚推出一段时间的时候利用微信来做点兼职赚点 ...
- Struts2国际化-getText()方法
转自https://blog.csdn.net/qq_43560838/article/details/83747604 一:简单理解 国际化简称i18n,其来源是英文单词 international ...
- 数位$dp$
数位\(dp\)搞了一上午才搞懂.靠这种傻\(X\)的东西竟然花了我一上午的时间. 数位\(dp\) 概念 数位\(dp\)就是强制你分类一些数,例如给你一段区间,然后让你求出不包含\(2\)的数的个 ...
- ListView的setOnItemClickListener回调不能执行的解决
如果ListView中的单个Item的view中存在checkbox,button等view,会导致ListView.setOnItemClickListener无效,事件会被子View捕获到,Lis ...
- 天津大学各种Latex模板共享链接
多元统计课最后Ppt里说要共享一下模板.这里给出链接 https://www.github.com/6gbluewind 注:写本文时还未上传 ************* 下午终于有网了,于是上传了一 ...
- MPP的进化 - 深入理解Batch和MPP优缺点
https://mp.weixin.qq.com/s/scXNfkpjktCZxBg3pYEUUA?utm_medium=hao.caibaojian.com&utm_source=hao.c ...
- Mojom IDL and Bindings Generator
Mojom IDL and Bindings Generator This document is a subset of the Mojo documentation. Contents Overv ...
- SSH概述与配置文件说明
一.什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录.在出现SSH之前,系统管理员需要登入远程服务器执行系统管理任务时,都是用telnet来实现的,telnet协议采用明文密码传 ...