如果这棵树不变的话,就是一个裸的点分树套平衡树,式子也很好推$di+dj<=ri+rj$,$ri-di>=dj-rj$ 平衡树维护$dj-rj$,然后查$ri-di$的$rank$即可。

但是点分树如果极度不平衡也就没有什么意义了。所以利用替罪羊树的思想,当某个子树极度不平衡时,就重新找重心,重建点分树。时间复杂度$O(nlg^2n)$,无旋Treap被卡,有旋Treap常数十分优秀。

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define L 1<<20
char _buf[L],*SS,*TT,c;
const int BufS=,md=;
char buf[BufS],*inss=buf,*outs=buf,num[];
inline void pl(register long long a){
if(!a){*outs++='',*outs++='\n';return;}
register int tp=;while(a)num[tp++]=a%,a/=;
while(tp--)*outs++=num[tp]+'';*outs++='\n';
}
#define gc() (SS==TT&&(TT=(SS=_buf)+fread(_buf,1,L,stdin),SS==TT)?0:*SS++)
int get()
{
for(c=gc();c<''||c>'';c=gc());
int x=c^'';
for(c=gc();c>=''&&c<='';c=gc())x=x*+(c^'');
return x;
}
#define N 100050
int n;
long long ans;
namespace Treap{
#define tp pair<Node*,Node*>
struct Node{
Node *ch[];
int key,val,size;
void pushup(){
size=ch[]->size+ch[]->size+;
}
Node(int k);
}*null=new Node(),*root[N],*root1[N];
Node :: Node(int k){
key=k;val=rand();size=;
ch[]=ch[]=null;
}
void init(){
null->ch[]=null->ch[]=null;
null->key=null->val=null->size=;
for(int i=;i<=::n;i++)root[i]=root1[i]=null;
}
int getrank(Node *now,int x){
int ans=;
while(now!=null){
if(now->key<x)ans+=now->ch[]->size+,now=now->ch[];
else now=now->ch[];
}
return ans;
}
void rotate(Node *&x,int d){
Node *y=x->ch[d];
x->ch[d]=y->ch[d^];
y->ch[d^]=x;
x->pushup();y->pushup();
x=y;
}
void insert(Node *&rt,int x){
if(rt==null)rt=new Node(x);
else{
int d=x>rt->key;
insert(rt->ch[d],x);
if(rt->ch[d]->val<rt->val)rotate(rt,d);
}
rt->pushup();
}
void dfs(Node *rt){
if(rt==null)return;
dfs(rt->ch[]);
dfs(rt->ch[]);
delete rt;
}
}
int head[N],e=;
struct edge{
int v,next;
}ed[N<<];
void add(int u,int v){
ed[e].v=v;ed[e].next=head[u];
head[u]=e++;
}
int dep[N],val[N],fa[N][],r[N],w[N];
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=;~i;i--)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=;~i;i--)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
}
int dis(int x,int y){
return val[x]+val[y]-*val[lca(x,y)];
}
int size[N],maxn[N],root,sum;
bool vis[N];
int f[N],S[N];
void getroot(int x,int fa){
size[x]=;maxn[x]=;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(v==fa||!vis[v])continue;
getroot(v,x);
size[x]+=size[v];
maxn[x]=max(maxn[x],size[v]);
}
maxn[x]=max(maxn[x],sum-size[x]);
if(maxn[x]<maxn[root])root=x;
}
void init(int x,int fa){
f[x]=fa;vis[x]=;
int all=sum;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(!vis[v])continue;
sum=size[v]<size[x]?size[v]:all-size[x];
root=;
getroot(v,);
init(root,x);
}
}
int T,tim[N];
void dfs1(int x,int fa,int s){
vis[x]=;sum++;S[x]=;tim[x]=T;
dfs(Treap::root[x]);Treap::root[x]=Treap::null;
dfs(Treap::root1[x]);Treap::root1[x]=Treap::null;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(v==fa||S[v]>s)continue;
dfs1(v,x,s);
}
}
void dfs2(int x,int fa,int en){
int now=x;
while(now!=en){
S[now]++;
Treap::insert(Treap::root[now],dis(x,now)-r[x]);
if(f[now])Treap::insert(Treap::root1[now],dis(x,f[now])-r[x]);
now=f[now];
}
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(v==fa||tim[v]!=T)continue;
dfs2(v,x,en);
}
}
void rebuild(int x){
int fa=f[x];T++;sum=;
dfs1(x,,S[x]);root=;
getroot(x,);
init(root,fa);
dfs2(x,,fa);
}
int query(int x){
int now=x;
int cnt=getrank(Treap::root[now],r[x]+);
while(f[now]){
cnt+=Treap::getrank(Treap::root[f[now]],r[x]-dis(x,f[now])+)
-Treap::getrank(Treap::root1[now],r[x]-dis(x,f[now])+);
now=f[now];
}
return cnt-;
}
void insert(int x){
if(x>)add(x,f[x]),add(f[x],x);
fa[x][]=f[x];
dep[x]=dep[fa[x][]]+;
val[x]=val[f[x]]+w[x];
for(int i=;(<<i)<=dep[x];i++)
fa[x][i]=fa[fa[x][i-]][i-];
S[x]++;
int now=x,ret=;
while(f[now]){
Treap::insert(Treap::root[now],dis(x,now)-r[x]);
Treap::insert(Treap::root1[now],dis(x,f[now])-r[x]);
S[f[now]]++;
if(S[now]>S[f[now]]*0.88)ret=f[now];
now=f[now];
}Treap::insert(Treap::root[now],dis(x,now)-r[x]);
if(ret)rebuild(ret);
ans+=query(x);
}
int main(){
n=get();n=get();maxn[]=N;
Treap::init();
for(int i=;i<=n;i++){
f[i]=get();w[i]=get();r[i]=get();
f[i]=f[i]^(ans%);
insert(i);
printf("%lld\n",ans);
}
return ;
}

bzoj3435 [Wc2014]紫荆花之恋的更多相关文章

  1. BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

  2. BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)

    Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是 ...

  3. bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)

    传送门(权限) 传送门(非权限) 题解 我终终终终终终于做出来啦!!! 作为一个没有学过替罪羊树的蒟蒻现场学了一下替罪羊树,作为一个平衡树都写数组版本的看着大佬的指针题解无语只能硬去理解然后照着抄了一 ...

  4. 【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT

    [BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从 ...

  5. bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400

    3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec  Memory Limit: 512 MBSubmit: 159  Solved: 40[Submit][Status] ...

  6. BZOJ 3435: [Wc2014]紫荆花之恋

    二次联通门 : BZOJ 3435: [Wc2014]紫荆花之恋 二次联通门 : luogu P3920 [WC2014]紫荆花之恋 /* luogu P3920 [WC2014]紫荆花之恋 怀疑人生 ...

  7. luogu P3920 [WC2014]紫荆花之恋

    LINK:紫荆花之恋 每次动态加入一个节点 统计 有多少个节点和当前节点的距离小于他们的权值和. 显然我们不能n^2暴力. 考虑一个简化版的问题 树已经给出 每次求某个节点和其他节点的贡献. 不难想到 ...

  8. BZOJ3435 & 洛谷3920 & UOJ55:[WC2014]紫荆花之恋

    https://www.lydsy.com/JudgeOnline/problem.php?id=3435 https://www.luogu.org/problemnew/show/P3920 ht ...

  9. 【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

随机推荐

  1. DIV与SPAN之间有什么区别

    DIV与SPAN之间有什么区别 DIV 和 SPAN 元素最大的特点是默认都没有对元素内的对象进行任何格式化渲染.主要用于应用样式表(共同点). 两者最明显的区别在于DIV是块元素,而SPAN是行内元 ...

  2. Python教程大纲

    缘起:最近想在部门推Python语言,写这个blog主要就是个教程大纲,之前先列出一些资源:Python历史:http://www.docin.com/p-53019548.html          ...

  3. SQL Server 表的管理_关于事务的处理的详解(案例代码)

    SQL Server 表的管理_关于事务的处理的详解(案例代码) 一.SQL 事务 1.1SQL 事务 ●事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序 ...

  4. Interesting卡常数

    C++ Interesting卡常数 作为一名OIer,在Noip中卡(kǎ 我就爱读kǎ)常数可以说是必备技巧.在此总结一下我所知卡常数的神奇手法: IO优化 fread 和 fwrite ,如果还 ...

  5. R语言学习 第十一篇:日期和时间

    R语言的基础包中提供了三种基本类型用于处理日期和时间,Date用于处理日期,它不包括时间和时区信息:POSIXct/POSIXlt用于处理日期和时间,其中包括了日期.时间和时区信息.R内部在存储日期和 ...

  6. JavaScript匿名自执行函数~function(){}

    原博客:https://blog.csdn.net/yaojxing/article/details/72784774 1.匿名函数的常见场景 js中的匿名函数是一种很常见的函数类型,比较常见的场景: ...

  7. 前端打包工具——build release介绍

    前言 对于前端开发者来说,资源打包是日常过程中一个必不可少的过程:目前我们大多数时候使用grunt.gulp.webpack这三个工具来完成这个工作:但是有一个特点就是我们没创建一个项目都要对应的去编 ...

  8. Hadoop-Yarn-框架原理及运作机制

    一.YARN基本架构 YARN是Hadoop 2.0中的资源管理系统,它的基本设计思想是将MRv1中的JobTracker拆分成了两个独立的服务:一个全局的资源管理器ResourceManager和每 ...

  9. Runc 简介

    RunC 是什么? RunC 是一个轻量级的工具,它是用来运行容器的,只用来做这一件事,并且这一件事要做好.我们可以认为它就是个命令行小工具,可以不用通过 docker 引擎,直接运行容器.事实上,r ...

  10. 在线引用js资源积累

    [jQuery]https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js[Vue]https://cdnjs.cloudfla ...