P2703【WC2014】紫荆花之恋(强数据版)

问题描述

强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花废物的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。
仔细看看的话,这棵大树实际上是一个带权树。每个时刻他会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵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 109)),与父亲节点之间的边权为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


考虑点分治,一个点对合法仅当他们不在同一颗子树上且dep[i]+dep[j]<=r[i]+r[j],dep表示点到根的距离dep[i]+dep[j]
移项得到dep[i]−r[i]<=r[j]−dep[j]dep[i]-r[i],那么只需要维护dep[i]−r[i]dep[i]-r[i]的信息即可。
需要支持添加,查找比某个数小的数的个数,那么用平衡树。

查询点分治树上两点距离的时候在原树上暴力LCA查找即可。

关于加点,直接在点分治树上添加即可,然后进行链查询,链修改,但是这样可能使得点分治树非常的不平衡
采用替罪羊树的思想解决,设定常数kiki,当过于不平衡时重构即可,这里kiki大概取0.8?0.8?
复杂度O(nlog3n)O(nlog^3n)

关于平衡树,用SBT比TREAP快了大概一倍。


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#define ll long long
#define N 300005
#define M 12345678
using namespace std;
const int mod=1e9;
const double ki=0.8;
typedef pair<int,int> par;
int n,R[N];
ll Ans;
int fa[N][20],dis[N][20],dep[N],S=18;
int TOT,LA[N],NE[N],EN[N],LE[N];
int Art[N],Ort[N],tot,ls[M],rs[M],v[M],w[M],si[M];
int rt,Min,SS[N],Fa[N],Si[N];
vector<int>to[N];
bool mark[N];
queue<int>bin;
void ADD(int x,int y,int z)
{TOT++;EN[TOT]=y;LE[TOT]=z;NE[TOT]=LA[x];LA[x]=TOT;
}
int LCA(int x,int y)
{if(dep[x]<dep[y])swap(x,y);int i,t=dep[x]-dep[y],s=0;for(i=0;i<=S;i++)if(t>>i&1)s+=dis[x][i],x=fa[x][i];if(x==y)return s;for(i=S;i>=0;i--)if(fa[x][i]!=fa[y][i]){s+=dis[x][i]+dis[y][i];x=fa[x][i];y=fa[y][i];}return s+dis[x][0]+dis[y][0];
}
void MT(int x)
{si[x]=si[ls[x]]+si[rs[x]]+1;}
int Merge(int x,int y)
{if(!x||!y)return x|y;if(w[x]<w[y]){rs[x]=Merge(rs[x],y);MT(x);return x;}else{ls[y]=Merge(x,ls[y]);MT(y);return y;}
}
par Split(int x,int k)
{if(k==0)return par(0,x);int l=ls[x],r=rs[x];if(k==si[l])return ls[x]=0,MT(x),par(l,x);if(k==si[l]+1)return rs[x]=0,MT(x),par(x,r);if(k<si[l]){par tmp=Split(l,k);ls[x]=tmp.second;MT(x);return par(tmp.first,x);}else{par tmp=Split(r,k-si[l]-1);rs[x]=tmp.first;MT(x);return par(x,tmp.second);}
}
int Rank(int x,int p)
{if(p==0)return 0;if(v[p]<=x)return si[ls[p]]+1+Rank(x,rs[p]);return Rank(x,ls[p]);
}
int Ins(int x,int &p)
{int t,k=Rank(x,p);par tmp=Split(p,k);if(bin.size())t=bin.front(),bin.pop();else t=++tot;ls[t]=rs[t]=0;v[t]=x;w[t]=rand();si[t]=1;p=Merge(tmp.first,t);p=Merge(p,tmp.second);
}
void Gmark(int x)
{mark[x]=0;for(int i=0;i<to[x].size();i++)Gmark(to[x][i]);
}
void Grt(int x,int s,int f)
{int i,y,Max=0;SS[x]=1;for(i=LA[x];i;i=NE[i]){y=EN[i];if(y==f||mark[y])continue;Grt(y,s,x);SS[x]+=SS[y];if(SS[y]>Max)Max=SS[y];}if(s-Max>Max)Max=s-Max;if(Max<Min)Min=Max,rt=x;
}
void Gdis(int x,int d,int f,int &k1,int &k2)
{Ins(d-R[x],k1);Ins(d-R[x],k2);for(int i=LA[x];i;i=NE[i])if(!mark[EN[i]]&&EN[i]!=f)Gdis(EN[i],d+LE[i],x,k1,k2);
}
void Del(int x)
{if(!x)return;bin.push(x);Del(ls[x]);Del(rs[x]);ls[x]=rs[x]=0;
}
void ReDC(int x)
{int i,y;mark[x]=1;Si[x]=1;to[x].clear();Del(Art[x]);Art[x]=0;Ins(-R[x],Art[x]);for(i=LA[x];i;i=NE[i]){y=EN[i];if(mark[y])continue;Min=1e9;Grt(y,SS[y],x);to[x].push_back(rt);Fa[rt]=x;Del(Ort[rt]);Ort[rt]=0;Gdis(y,LE[i],0,Art[x],Ort[rt]);}for(i=0;i<to[x].size();i++)ReDC(to[x][i]),Si[x]+=Si[to[x][i]];
}
void Rebuild(int x)
{int i,p=Fa[x];Gmark(x);Min=1e9;Grt(x,Si[x],p);if(p){for(i=0;i<to[p].size();i++)if(to[p][i]==x){to[p][i]=rt;break;}}Ort[rt]=Ort[x];if(x!=rt)Ort[x]=0;//!!!!!!Fa[rt]=Fa[x];ReDC(rt);
}
void Solve(int x,int f,int le)
{int i,j,k=f,d,p=Fa[f],las=x;mark[x]=1;Si[x]=1;Fa[x]=f;Si[f]++;Ins(-R[x],Art[x]);to[f].push_back(x);Ins(le-R[x],Ort[x]);Ans+=Rank(R[x]-le,Art[f]);Ins(le-R[x],Art[f]);while(p){d=LCA(x,p);Ans+=Rank(R[x]-d,Art[p]);Ans-=Rank(R[x]-d,Ort[k]);Ins(d-R[x],Art[p]);Ins(d-R[x],Ort[k]);Si[p]++;k=p;p=Fa[p];}for(p=x;Fa[p];p=Fa[p])if(1.0*Si[p]>=1.0*Si[Fa[p]]*ki)las=Fa[p];if(las!=x)Rebuild(las);
}
int main_main()
{srand(time(NULL));int i,j,k,x,y,z;scanf("%d%d",&x,&n);for(i=1;i<=n;i++){scanf("%d%d%d",&x,&y,&z);if(i==1){printf("0\n");R[i]=z;Si[i]=1;Ins(-R[i],Art[i]);mark[i]=1;continue;}fa[i][0]=x^(Ans%mod);dep[i]=dep[fa[i][0]]+1;dis[i][0]=y;R[i]=z;ADD(fa[i][0],i,y);ADD(i,fa[i][0],y);for(j=1;j<=S;j++)fa[i][j]=fa[fa[i][j-1]][j-1],dis[i][j]=dis[fa[i][j-1]][j-1]+dis[i][j-1];Solve(i,fa[i][0],y);printf("%lld\n",Ans);}
}
const int main_stack=16;
char my_stack[128<<21];
int main() {__asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory");__asm__("movl %%eax, %%esp;\n"::"a"(my_stack+sizeof(my_stack)-main_stack):"%esp");main_main();__asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp");return 0;
}  

NKOJ 2703 (WC 2014)紫荆花之恋 (点分治+平衡树+替罪羊)相关推荐

  1. python画图绘制紫荆花_数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋(示例代码)...

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

  2. BZOJ 3435: [Wc2014]紫荆花之恋 【(替罪羊树式)动态点分治 + Treap】

    BZOJ 传送门 洛谷传送门 题目分析: 似乎做过几道点分树的题之后题解还是比较好懂的. 这位dalao的题目分析非常的到位,Orz. PoPoQQQ的具体解读也非常的清晰,Orz. R i + R ...

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

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

  4. [UOJ55]紫荆花之恋

    第一次打"真正的"动态点分 如果树是静态的,直接点分:用$d_x$代表$x$到分治中心的距离,限制条件即为$d_i+d_j\leq r_i+r_j$,考虑枚举$j$,那么我们要查询 ...

  5. 【WC2014】紫荆花之恋【替罪羊思想】【动态点分树】【替罪羊树】

    传送门 题意:有一棵开始时没有结点的树,nnn次询问,每次新加一点并给定父结点.到父亲的距离.参数rir_iri​,并询问满足dist(u,v)≤ru+rvdist(u,v)\leq r_u+r_vd ...

  6. 半小时写完替罪羊重构点分树做动态动态点分治之紫荆花之恋的wyy贴心指导

    刷题训练 初学者 有一定语言基础,但是不了解算法竞赛,水平在联赛一等奖以下的. 参考书:<算法竞赛入门经典--刘汝佳>,<算法竞赛入门经典训练指南--刘汝佳> 题库:洛谷(历年 ...

  7. linux每个磁盘大小,linux磁盘占用跟每个文件夹大小总和不符

    [LeetCode] Assign Cookies 分点心 Assume you are an awesome parent and want to give your children some c ...

  8. 新年扯皮以及一些比较正经的东西

    扯皮 去年写了个高三之前OI生涯的回忆录,手贱在最后加了个"未完待续".当然即使是现在我还是想把这个东西一直写到我真正退役的.只不过现在还没想好怎么写,甚至不确认是否应该开始写了. ...

  9. WC2019 划水记

    写在前面: 本篇是擅长咕咕咕的\(\text{BLUESKY007}\)同学难得不咕写的游记,将会记录\(WC2019(2019.1.24(Day\ 0)\sim2019.1.30(Day\ 6))\ ...

最新文章

  1. CVPR2019论文解读:单眼提升2D检测到6D姿势和度量形状
  2. Coins and Queries(map迭代器+贪心)
  3. mysql 字符串中取整_MySQL取整
  4. STRUTS2.X之使用validate方法验证数据
  5. php查询变量类型,php判断变量类型常用方法
  6. [转载] Java中变量与常量
  7. 错误代码666020_Windows 系统错误代码大全
  8. java的环境变量_java学习册|JDK|环境变量
  9. 手机充满电不拔有什么影响吗?
  10. bzoj 3196二逼平衡树 线段树套平衡树
  11. prepared statement mysql_MySQL之 Statement实现及PreparedStatement实现
  12. 晶体管电路设计 上 铃木雅臣 学习体会
  13. 概率论与数理统计学习笔记——第7讲——连续型随机变量(2.5.4指数分布及其与泊松分布的关系)
  14. 2021window10下的IDEA安装
  15. activiti踩坑2-camunda-modeler设计器与activiti7不兼容
  16. Android Studio 3.5以后 Plugins中搜索不到flutter插件,本地无法安装??
  17. firefox正在安装组件,以便播放此页面上的音频或视频
  18. 云主机怎么安装mysql_华为云主机安装Mysql
  19. 销售——LPN(License Plate Number)
  20. android多个悬浮窗口的实现,android实现桌面移动悬浮窗口

热门文章

  1. 基于IO多路复用的TCP客户端
  2. 五分钟实现 pdf 分页
  3. 【算法百题之四十二】罗马数字转整数
  4. 微信公众号消息通知(原生)
  5. 解决iPhone无法连接iTunes
  6. 多项式(带余)除法学习笔记
  7. 初中使用计算机教学反思,谈初中信息技术教学反思
  8. 原生Android设置sim卡锁定,开启SIM卡密码保护
  9. 多分类下的ROC曲线和AUC
  10. 小目标检测模型总结+SNIP+SNIPER