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]紫荆花之恋(动态点分治+替罪羊思想)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
随机推荐
- 你的Android应用完全不需要那么多的权限
Android系统的权限从用户的角度来看有时候的确有点让人摸不着头脑.有时候可能你只需要做一些简单的事情(对联系人的信息进行编辑),却申请了远超你应用所需的权限(比如访问所有联系人信息的权限). 这很 ...
- 32.AngularJS 表达式
转自:https://www.cnblogs.com/best/tag/Angular/ AngularJS 表达式写在双大括号内:{{ expression }}. AngularJS 表达式把数据 ...
- MyBatis多参数传递之注解方式示例--转
原文地址:http://legend2011.blog.51cto.com/3018495/1015003 若映射器中的方法只有一个参数,则在对应的SQL语句中,可以采用#{参数名}的方式来引用此参数 ...
- k-meas非监督聚类分析
实验名称: k-meas非监督聚类分析 一.实验目的和要求 目的: 加深对非监督学习的理解和认识 掌握聚类方法K-Means算法的设计方法 要求: 根据聚类数据,采用k-Means聚类 ...
- jquery判断页面元素是否存在
在传统的Javascript里,当我们对某个页面元素进行某种操作前,最好先判断这个元素是否存在.原因是对一个不存在的元素进行操作是不允许的. 例如: document.getElementById(& ...
- 最标准的 Java MySQL 连接
package com.runoob.test; import java.sql.*; public class MySQLDemo { // JDBC 驱动名及数据库 URL static fina ...
- vue.js技巧小计
//删除数组索引方法01 del (index) { this.arr.splice(index ,1); } //删除数组索引方法01 del (index) { this.$delete(this ...
- php基础:define()定义常数函数
define(); 常量类似变量,不同之处在于: 在设定以后,常量的值无法更改 常量名不需要开头的美元符号 ($) 作用域不影响对常量的访问 常量值只能是字符串或数字 <?php define( ...
- CentOS 7.4 ifconfig, ip/ss, nmcli, nmtui, 配置文件 修改ip信息用法
CentOS 7.4 ifconfig, ip/ss, nmcli, nmtui, 配置文件 修改ip信息用法 CentOS 7.4 中, 网卡命名方式发生改变, 可预测功能命名: 网卡简要名称组成格 ...
- NOIP 2012 疫情控制(二分+贪心+倍增)
题解 二分时间 然后一个显然的事是一个军队向上爬的越高它控制的点越多 所以首先军队尽量往上爬. 当一个军队可以爬到根节点我们记录下它的剩余时间T和它到达根结点时经过的根节点的子节点son. 当一个军队 ...