【题目描述】

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

仔细看看的话,这棵大树实际上是一个带权树。每个时刻他会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精
灵。小精灵是很萌但是也很脆弱的生物,每个小精灵i都有一个感受能力ri,小精灵i,j成为朋友当且仅当在树上i和j的距离
dist(i,j)<=ri+rj,其中dist(i,j)表示在这棵树上i和j的唯一路径上所有边的边权和。

强强和萌萌很好奇每次新长出了一个叶子节点之后这棵树上总共有几对朋友。

我们假定这棵树一开始为空,节点按照加入的顺序从1开始编号。由于强强非常好奇,你必须在每次出现新的节点后马上给出总共的朋友对数不能拖延哦。

【输入格式】

输入文件共有n+2行。

第一行包含一个正整数T,表示测试点编号。

第二行包含一个正整数n,表示总共要加入的节点数。

我们令加入前的总工朋友对数是last_ans,在一开始时last_ans=0。

接下来n行中第i行有三个数ai,ci,ri,表示节点i的父亲节点的编号为(ai xor ( last_ans mod 10^9)),与父亲节点之间的边权为ci,节点i上小精灵的感受能力为ri。

注意a1=c1=0,表示1号点事根节点。对于i>=2,父亲节点的编号至少是1,至多是i-1。

【输出格式】

输出文件包含n行,每行输出1个整数,表示加入第i个点之后,树上共有几对朋友。

【样例输入】

0
5
0 0 6
1 2 4
0 9 4
0 5 5
0 2 4

【样例输出】

0
1
2
4
7   对于每一对点,通过之间路径的最高点更新答案,枚举最高点(log)用平衡树维护并查找(log),但是不断新加点会导致树高太大,算法退化。这时发现用点分治的思想把树划分,得到一棵新树,若维护了现在每个点到根节点路径上每个dep的距离,还是一样的可以求得答案,这样重新构建树可以解决退化问题。
  发现自己的代码很短,其实有什么10行AC代码,但事实上还是这个算法。
 #include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int N=,M=;
int cnt,fir[N],to[N*],val[N*],nxt[N*];
void addedge(int a,int b,int v){
nxt[++cnt]=fir[a];
to[fir[a]=cnt]=b;
val[cnt]=v;
}
int pim,top,pool[N],sz[M];
int ch[M][],key[M],fix[M];
#define lc ch[x][0]
#define rc ch[x][1]
int Newnode(int k){
int x=top?pool[top--]:++pim;
sz[x]=;lc=rc=;key[x]=k;
fix[x]=rand();return x;
}
#define c (k>=key[x])
#define g ch[x][c] void Push_up(int x){sz[x]=sz[lc]+sz[rc]+;} void Rotate(int x,int &y,int f){
ch[y][f]=ch[x][f^];ch[x][f^]=y;
Push_up(y);Push_up(x);y=x;
} void Insert(int &x,int k){
if(!x){x=Newnode(k);return;}Insert(g,k);
sz[x]+=;if(fix[x]>fix[g])Rotate(g,x,c);
} int Query(int x,int k){
if(!x)return ;
if(!c)return Query(g,k);
return Query(g,k)+sz[lc]+;
} void Delete(int &x){
if(!x)return;
pool[++top]=x;x=;
if(lc)Delete(lc);
if(rc)Delete(rc);
} long long ans;
int n,fa[N],v[N],r[N];
int rt[N],pt[N],dep[N];
int G[N][],SZ[N],P,w,tp;
int F[N],H[N],S,mm; void Get_G(int x,int f,int d){
F[x]=H[x]=;
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=f&&dep[to[i]]>=d){
Get_G(to[i],x,d);
H[x]=max(H[x],F[to[i]]);
F[x]+=F[to[i]];
}
H[x]=max(H[x],S-F[x]);
if(!P||H[P]>H[x])P=x;
} void DFS(int x,int f,int d,int v,int &t){
F[x]=;dep[x]=d+;
G[x][d]=v;Insert(t,v-r[x]);
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=f&&dep[to[i]]>=d){
DFS(to[i],x,d,v+val[i],t);
F[x]=F[x]+F[to[i]];
}
} void Rebuild(int x,int f,int d,int m,int sz){
P=;S=sz;Get_G(x,,d);fa[x=P]=f;Delete(rt[x]);
SZ[x]=sz;DFS(x,,d,,rt[x]);dep[x]=d;
if(pt[x]!=mm)Delete(pt[x]);pt[x]=m;
for(int i=fir[x],p;i;i=nxt[i])
if(dep[to[i]]>=d){
p=;DFS(to[i],,d+,val[i],p);
Rebuild(to[i],x,d+,p,F[to[i]]);
}
} int main(){
freopen("flowera.in","r",stdin);
freopen("flowera.out","w",stdout);
scanf("%d%d",&tp,&n);
scanf("%d%d%d",fa+,v+,r+);
Insert(rt[],-r[]);SZ[]=;puts("");
for(int x=;x<=n;x++){
scanf("%d%d%d",fa+x,v+x,r+x);
fa[x]^=ans%;
addedge(x,fa[x],v[x]);
addedge(fa[x],x,v[x]);
dep[x]=dep[fa[x]]+; for(int i=;i<dep[x];i++)
G[x][i]=G[fa[x]][i]+v[x]; for(int y=x;y!=;y=fa[y]){
SZ[y]+=;w=r[x]-G[x][dep[y]];
ans+=Query(rt[y],w);
Insert(rt[y],-w);
if(fa[y]){
w=r[x]-G[x][dep[fa[y]]];
ans-=Query(pt[y],w);
Insert(pt[y],-w);
if(SZ[y]>SZ[fa[y]]*.)P=fa[y];
}
}
printf("%lld\n",ans);
if(P)Rebuild(P,fa[P],dep[P],mm=pt[P],SZ[P]),P=;
}
return ;
}

数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋的更多相关文章

  1. [WC 2014]紫荆花之恋

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

  2. 数据结构(动态树):COGS 27. [WC 2006] 水管局长

    27. [WC 2006] 水管局长 ★★★☆   输入文件:tube.in   输出文件:tube.out   简单对比时间限制:3 s   内存限制:128 MB [问题描述 ] SC 省 MY ...

  3. 【WC2014】紫荆花之恋(替罪羊重构点分树 & 平衡树)

    Description 若带点权.边权的树上一对 \((u, v)\) 为 friend,那么需要满足 \(\text{dist}(u, v) \le r_u + r_v\),其中 \(r_x\) 为 ...

  4. COJ 0970 WZJ的数据结构(负三十)树分治

    WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...

  5. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  6. luoguP3920 [WC2014]紫荆花之恋 动态点分治 + 替罪羊树

    意外的好写..... 考虑点分 \(dis(i, j) \leq r_i + r_j\) 对于过分治中心一点\(u\),有 \(dis(i, u) - r_i = dis(j, u) + r_j\) ...

  7. LOJ#6463 AK YOI 树分治+线段树合并

    传送门 既然是树上路径统计问题,不难想到要使用树分治,这里以点分治为例 由点分治的性质,每层只需要考虑经过重心的路径 因为需要维护路径长度在一定范围内的最大权值和,所以要用一个数据结构维护一下到根节点 ...

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

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

  9. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

随机推荐

  1. .Net程序员学习Linux(二)

    本次知识点:递归命令符,wc命令,文档编辑器 vi的简单使用,文本常用操作命令,find查询文件命令,grep匹配文本中对应的关键字 递归命令符 递归对于程序猿来说不默认,经常用于级联关系,一层套一层 ...

  2. [弹出消息] C#MessageBox帮助类 (转载)

    点击下载 MessageBox.rar 主要功能如下所示1.显示消息提示对话框 2.控件点击 消息确认提示框 3.显示消息提示对话框,并进行页面跳转 4.输出自定义脚本信息 /// <summa ...

  3. UDP,TCP理解。

    UDP: 面向无连接, 每个数据大小限制在64K内 因为面向无连接,所以就是不可靠协议. 将数据和源和谜底封装到数据包当中,不需要建立连接.速度快(就像送快递一样,管你在不可以先到你门口) 用处:聊天 ...

  4. vsftpd安装指南

    如果您用的是Fedora 或Redhat 系统,可以用下面的命令在线安装: [root@localhost ~]# yum install vsftpd 如果是debian 类系统,可以用apt 来在 ...

  5. iOS 开发工具

    Github 社区 https://github.com/ iOS 开发类库 http://www.code4app.com/thread-7831-1-1.html (出处: Code4App-iO ...

  6. iOS军火库-好用的ActionSheetView

    GitHub地址 一个自定义的ActionSheetView,支持显示标题,默认选中,使用block回调. 使用说明 [GLActionSheet showWithDataSource:@[@&quo ...

  7. jQuery 尺寸

    通过 jQuery,很容易处理元素和浏览器窗口的尺寸. jQuery 尺寸 方法 jQuery 提供多个处理尺寸的重要方法: width() height() innerWidth() innerHe ...

  8. 数据库(学习整理)----4--Oracle数据查询(基础点1)

    其他: 计算机中的内存是线性的,一维. length('')计算字符的个数,而不是字节的个数 Oracle中的日期类型和数值类型的数据可以做运算符(>,=,<,<>)比较 如果 ...

  9. Codevs 1010 过河卒 2002年NOIP全国联赛普及组

    1010 过河卒 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 如图,A 点有一个过河卒 ...

  10. C++语言体系设计哲学的一些随想(未完待续)

    对于静态类型语言,其本质目标在于恰当地操作数据,得到期望的值.具体而言,需要: (1)定义数据类型 你定义的数据是什么,是整形还是浮点还是字符.该类型的数据可以包含的值的范围是什么. (2)定义操作的 ...