【题目描述】

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

仔细看看的话,这棵大树实际上是一个带权树。每个时刻他会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精
灵。小精灵是很萌但是也很脆弱的生物,每个小精灵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. Gym 100187M-Heaviside Function

    题意:给定函数: f(x) = θ(s1x - a1) + θ(s2x - a2) + ... + θ(snx - an), where si =  ± 1. Calculate its values ...

  2. linux du 显示目录下的各个子目录的大小

    use  command du  display estimate file space usage size of subdirectories [oracle@ahjcyl-db backup]$ ...

  3. FTPClient文件下载

    一.FTPClient下载文件所需要的jar包: org.apache.commons.net  [commons-net-3.4.jar] 二.FTPClient的连接和关闭 //FTPClient ...

  4. Java 对象属性的遍历

    package com.cn.mybatis.test; import java.io.IOException; import java.io.InputStream; import java.lan ...

  5. Repeater 动态增加删除一行

    文章参考:文章参考http://www.cnblogs.com/dataadapter/archive/2012/06/25/2562885.html 效果: 前台代码: <%@ Page La ...

  6. 使用gdb跟踪Linux内核启动过程(从start_kernel到init进程启动)

    本次实验过程如下: 1. 运行MenuOS系统 在实验楼的虚拟机环境里,打击打开shell,使用下面的命令 cd LinuxKernel/ qemu -kernel linux-/arch/x86/b ...

  7. 当 IDENTITY_INSERT 设置为 OFF 时,不能向表 中的标识列插入显式值错误的解决方法

    一个主键.两个外键,把两个外键改为非空就行了. CREATE TABLE [dbo].[User_Compare]( ,) NOT NULL, [UserId] [int] NOT NULL, [Pa ...

  8. iOS push全方位解析(二)【译文】"——生成OpenSSL证书,Provisioning Profile

    这是一篇来自raywenderlich的教程,内容翔实!结构简单透彻.讲解循序渐进.文章质量上乘!是一篇难的的博文!使用半瓶的英语水平翻译了一下: 1.[iOS push全方位解析](一) push的 ...

  9. Maven介绍,包括作用、核心概念、用法、常用命令、扩展及配置

    由浅入深,主要介绍maven的用途.核心概念(Pom.Repositories.Artifact.Build Lifecycle.Goal).用法(Archetype意义及创建各种项目).maven常 ...

  10. 2016021904 - 如何使用Memory Analyzer

    如何使用Memory Analyzer呢? 0.有内存溢出的代码code.<深入理解java虚拟机>中代码 package neutron.oom.heap; import java.ut ...