【题目描述】

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

仔细看看的话,这棵大树实际上是一个带权树。每个时刻他会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精
灵。小精灵是很萌但是也很脆弱的生物,每个小精灵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. C#中隐式类型本地变量var

    在新接触的项目中,看到很多声明变量时用var.只记得在javascript中声明变量用var.今天在家里看C#和.Net高级编程,看到隐式变量这一块,就总结一下C# 中隐式变量var的用法. 1.C# ...

  2. oracle redo日志维护

    环境 OS:Red Hat Linux As 5 DB:10.2.0.1 1.添加日志组 alter database add logfile group 4 ('/u01/app/oracle/or ...

  3. Oracle 检验身份证是否正确的存储过程

    ) ) ); ); ); ); ); ); ); ; , , , , , , , , , , , , , , , , , ); ;  , ) );  ..  loop )) ) ); , )), ), ...

  4. 在ASP.NET 中调用RSACryptoServiceProvider失败,提示未找到文件

    在本地开发环境调试下,调试这个RSA加密是没问题的,但是部署到IIS就会报错. 原来是,在本地vs调试与IIS上运行是存在权限差异的.本地调试权限最大,IIS 次之. 所以在我们声明CspParame ...

  5. Linux系统查找文件find命令使用(不断更新)

    个人博客地址:http://www.cnblogs.com/wdfwolf3/. 使用格式:find  [查找目录]  [查找规则]  [查找完后执行的操作] [查找目录] 即要查找的路径,可以使用 ...

  6. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  7. Windows phone 之XML序列化与反序列化

    为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...

  8. asp.net Linq 实现分组查询

    首先我们还是先建立一个person.cs类 public class person { public string name { get; set; } public int age { get; s ...

  9. C# 禁止 Webbrowser 控件的弹出脚本错误对话框

    当IE浏览器遇到脚本错误时浏览器,左下 角会出现一个黄色图标,点击可以查看脚本错误的详细信息,并不会有弹出的错误信息框.当我们使用 WebBrowser控件时有错误信息框弹出,这样程序显的很不友好,而 ...

  10. sharepoint给文档库每个数据条添加权限

    前言 老大任务,做一个读取文档库把里面的每一条数据添加权限.挺起来很简单,但是做起来,还是很简单,哈哈.因为我没有接触过这些代码,所以得不断的请教了.大题明白了,简单实现了一下,应用控制台先做了一下简 ...