数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋
2016-09-10 21:27
441 查看
【题目描述】
强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这棵大树实际上是一个带权树。每个时刻他会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精
灵。小精灵是很萌但是也很脆弱的生物,每个小精灵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=100010,M=20000010; int cnt,fir ,to[N*2],val[N*2],nxt[N*2]; void addedge(int a,int b,int v){ nxt[++cnt]=fir[a]; to[fir[a]=cnt]=b; val[cnt]=v; } int pim,top,pool ,sz[M]; int ch[M][2],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]=1;lc=rc=0;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]+1;} void Rotate(int x,int &y,int f){ ch[y][f]=ch[x][f^1];ch[x][f^1]=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]+=1;if(fix[x]>fix[g])Rotate(g,x,c); } int Query(int x,int k){ if(!x)return 0; if(!c)return Query(g,k); return Query(g,k)+sz[lc]+1; } void Delete(int &x){ if(!x)return; pool[++top]=x;x=0; if(lc)Delete(lc); if(rc)Delete(rc); } long long ans; int n,fa ,v ,r ; int rt ,pt ,dep ; int G [50],SZ ,P,w,tp; int F ,H ,S,mm; void Get_G(int x,int f,int d){ F[x]=H[x]=1; 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]=1;dep[x]=d+1; 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=0;S=sz;Get_G(x,0,d);fa[x=P]=f;Delete(rt[x]); SZ[x]=sz;DFS(x,0,d,0,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=0;DFS(to[i],0,d+1,val[i],p); Rebuild(to[i],x,d+1,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+1,v+1,r+1); Insert(rt[1],-r[1]);SZ[1]=1;puts("0"); for(int x=2;x<=n;x++){ scanf("%d%d%d",fa+x,v+x,r+x); fa[x]^=ans%1000000000; addedge(x,fa[x],v[x]); addedge(fa[x],x,v[x]); dep[x]=dep[fa[x]]+1; for(int i=0;i<dep[x];i++) G[x][i]=G[fa[x]][i]+v[x]; for(int y=x;y!=0;y=fa[y]){ SZ[y]+=1;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]]*.88)P=fa[y]; } } printf("%lld\n",ans); if(P)Rebuild(P,fa[P],dep[P],mm=pt[P],SZ[P]),P=0; } return 0; }
相关文章推荐
- [替罪羊树 动态点分治 替罪羊式重构] BZOJ 3435 [Wc2014]紫荆花之恋 & UOJ #55 【WC2014】紫荆花之恋
- NKOJ 2703 (WC 2014)紫荆花之恋 (点分治+平衡树+替罪羊)
- bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400
- uoj#55./bzoj3435 【WC2014】紫荆花之恋 //替罪羊式重构点分树
- BZOJ3435: [Wc2014]紫荆花之恋 动态树分治 替罪羊树
- bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)
- Wc2014 紫荆花之恋
- 数据结构之重构数组
- WC2014-紫荆花之恋
- BZOJ 3181: [Coci2012]BROJ 【数据分治(暴力+(二分&&容斥))
- 数据结构(Splay平衡树): [NOI2007] 项链工厂
- sdutoj 3363 数据结构实验之图论七:驴友计划 (暴力深搜最短路)
- hrbust 1547 基础数据结构——单链表(2)【水题-暴力预处理】
- 【下资源:xiazy.net】2014传智播客C++第五期(数据结构与算法)两个月+第三期完整版
- 数据结构与算法学习笔记——二叉树重构(递归)
- 2015-10-22 前思后想,决定重构表结构,免得这个APP死在数据表设计上
- 数据结构(括号序列,线段树||点分治,堆):ZJOI 2007 捉迷藏
- [数据结构暴力] zoj 3749 Chameleon
- 数据结构实验:AVL平衡树做出用户登录系统(dos界面)
- UVALive 7146 (贪心+少许数据结构基础)2014acm/icpc区域赛上海站