【 [Wc2014]紫荆花之恋】(⊙o⊙)动态点分治重构
久闻紫荆花之恋大名,今日一见,果然名不虚传,不过名字确实挺美的owo
luogu3920
UOJ55
3435: [Wc2014]紫荆花之恋
Time Limit: 240 Sec Memory Limit: 512 MB Submit: 688 Solved: 235 [Submit][Status][Discuss]Description
强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这个大树实际上是一个带权树。每个时刻它会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + R! ,其中 dist(i, j)表示在这个树上从 i 到 j 的唯一路径上所有边的边权和。强强和萌萌很好奇每次新长出一个叶子节点之后,这个树上总共有几对朋友。
我们假定这个树一开始为空,节点按照加入的顺序从 1开始编号。由于强强非常好奇, 你必须在他每次出现新节点后马上给出总共的朋友对数,不能拖延哦。
Input
共有 n + 2 行。
第一行包含一个正整数,表示测试点编号。
第二行包含一个正整数 n ,表示总共要加入的节点数。
我们令加入节点前的总共朋友对数是 last_ans,在一开始时它的值为0。
接下来 n 行中第 i 行有三个数 ai, bi, ri,表示节点 i 的父节点的编号为 ai xor (last_ans mod 10^9) (其中xor 表示异或,mod 表示取余,数据保证这样操作后得到的结果介于 1到i – 1之间),与父节点之间的边权为 ci,节点 i 上小精灵的感受能力值为r!。
注意 a1 = c1 = 0,表示 1 号点是根节点,对于 i > 1,父节点的编号至少为1。
Output
包含 n 行,每行输出1 个整数, 表示加入第 i 个点之后,树上有几对朋友。
Sample Input
0
5
0 0 6
1 2 4
0 9 4
0 5 5
0 2 4
Sample Output
0
1
2
4
7
HINT
1<=Ci<=10000
Ai<=2*10^9
Ri<=10^9
N<=100000
我们发现有万恶之源--强制在线,我们如果不强制在线,就是一个套路的动态点分治了,同样每个点维护自己子树信息和到该子树到父亲的信息,对于lcax来说就是因为disi + disj<= ri + rj,也就是disi - ri <= rj - disj,我们把disi - ri加入平衡树里面,然后查询的时候查询rj - disj 的排名就可以了,但是,但是,但是orz。
好吧,这里我们就要用到替罪羊的思想了,不平衡就重构。就是把他管的那一颗点分子树信息全部消除,然后一个点分树新建,找重心,加入距离,恩,看上去似乎还好,也没什么。
只有自己调试的时候痛苦不已。我之前写的时候居然平衡树替罪羊一直重构都没起到作用,也就是说一直是不平衡树,居然能拿到90,,加上大家都说卡常,我还以为常数痴了,一直在卡常。没想到啊orz。
7500B LJ代码:
#include<stdio.h> #include<cstdio> #include<algorithm> #include<iostream> #include<vector> #include<map> using namespace std; typedef long long ll; // int JSCNT; namespace bz{ const int maxn = 100005; int fa[17][maxn],dep[maxn];ll dis[maxn]; int glca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); int dd = dep[x] - dep[y]; for(int i=0;dd;i++,dd>>=1) if(dd&1) x = fa[i][x]; if(x==y) return x; for(int i=16;i>=0;i--) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y]; return fa[0][x]; } ll gdis(int x,int y) { int lcc = glca(x,y); return dis[x] + dis[y] - 2*dis[lcc]; } void add(int x,int f,int C) { dep[x] = dep[f] + 1; fa[0][x] = f; dis[x] = dis[f] + C; for(int i=1;i<=16;i++) fa[i][x] = fa[i-1][fa[i-1][x]]; } } // char buf[1<<20],*p1,*p2; #define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++) inline ll _R() { char t=GC; ll x=0; while(!isdigit(t)) t=GC; while(isdigit(t)) x=x*10+t-48,t=GC; return x; } char pbuf[1<<20],*pp=pbuf; void push(const char c) { if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf; *pp++=c; } inline void _W(ll x) { static int sta[35]; int top=0; do{sta[top++]=x%10,x/=10;}while(x); while(top) push(sta[--top]+'0'); push('\n'); } // namespace bt{ const int maxn = 4000005; struct node{ node *ls,*rs;ll dat;int siz,ct;ll mx; }z[maxn],*nul,*pool[maxn],**RT; int lj,tot; void upd(node *&p) { p->siz = p->ls->siz + p->rs->siz + p->ct; p->mx = p->dat; if(p->ls!=nul) p->mx = max(p->ls->mx,p->mx); if(p->rs!=nul) p->mx = max(p->rs->mx,p->mx); } vector<int>ve[maxn]; bool isbad(node *&p) { if(max(p->ls->siz,p->rs->siz)>p->siz*0.88) return 1; return 0; } node* nwnode(int x) { node *p = lj?pool[lj--]:&z[++tot]; p->ls = p->rs = nul; p->siz = p->ct = 1; p->dat = p->mx = x; return p; } void ins(node *&p,int x) { if(p==nul) { p = nwnode(x); return ; } if(x==p->dat) p->ct++; else if(x<p->dat) ins(p->ls,x); else ins(p->rs,x); if(isbad(p)) RT = &p; upd(p); } ll lower(node*&p,ll x) { if(p==nul) return 0; if(p->mx<=x) return p->siz; if(p->dat==x) return p->ls->siz + p->ct; if(p->dat<x) return p->ls->siz + p->ct + lower(p->rs,x); return lower(p->ls,x); } void init() { nul=z; nul->ls=nul->rs=nul; } int stad[maxn],stac[maxn],tp; void tra(node *&p) { if(p==nul) return; tra(p->ls); ++tp; stad[tp] = p->dat; stac[tp]=p->ct; pool[++lj]=p; tra(p->rs); } void build(node *&p,int l,int r) { int mid = (l+r)>>1; p = nwnode(stad[mid]); p->ct = p->siz = stac[mid]; if(l<mid) build(p->ls,l,mid-1); if(mid<r) build(p->rs,mid+1,r); upd(p); } void rebuild() { tp=0; tra(*RT); build(*RT,1,tp); RT = &nul; } node *sont[maxn],*treet[maxn]; // sont --> to father treet --> to it void add(node *&p,int x) { RT = &nul; ins(p,x); if(*RT!=nul) rebuild(); } void clr(node *&p) { tp = 0; tra(p); p = nul; } }// int n; namespace dft{ const int maxn = 300005; int r[maxn]; int la[maxn],owo,en[maxn],nt[maxn],len[maxn]; int vis[maxn],vivi[maxn],tim; void adg(int x,int y,int le) { en[++owo]=y; nt[owo]=la[x]; la[x]=owo; len[owo]=le; en[++owo]=x; nt[owo]=la[y]; la[y]=owo; len[owo]=le; } vector<int>sons[maxn]; int fa[maxn],VV; void fuckall(int x) { vis[x] = tim; bt::clr(bt::treet[x]); for(auto y:sons[x]) { if(fa[y]!=x) continue; fuckall(y); bt::clr(bt::sont[y]); } sons[x].clear(); } int rtsz,rrt,sm,sz[maxn]; void gsi(int x,int ba) { sz[x]=1; for(int it=la[x];it;it=nt[it]){ int y = en[it]; if(vis[y]!=tim||vivi[y]==tim||y==ba) continue; gsi(y,x); sz[x] += sz[y]; } } void grt(int x,int ba) { int sso = 0; for(int it=la[x];it;it=nt[it]) { int y = en[it]; if(vis[y]!=tim||vivi[y]==tim||y==ba) continue; grt(y,x); sso = max(sso,sz[y]); } sso = max(sso,sm-sz[x]); if(sso<rtsz) rtsz=sso,rrt=x; } void insdeep(int x,int ba,ll dd) { bt::stad[++bt::tp]=dd-r[x]; for(int it=la[x];it;it=nt[it]) { int y = en[it]; if(vis[y]!=tim||vivi[y]==tim||y==ba) continue; insdeep(y,x,dd+len[it]); } } void jianli(bt::node *&p) { if(!bt::tp) return; sort(bt::stad+1,bt::stad+1+bt::tp); int now = 1; bt::stac[1] = 1; for(int i=2;i<=bt::tp;i++) { if(bt::stad[i]==bt::stad[now]) bt::stac[now]++; else bt::stad[++now]=bt::stad[i],bt::stac[now]=1; } bt::build(p,1,now); } void DC(int x) { vivi[x] = tim; bt::tp = 0; insdeep(x,0,0); jianli(bt::treet[x]); for(int it=la[x];it;it=nt[it]) { int y = en[it]; if(vis[y]!=tim||vivi[y]==tim) continue; gsi(y,x); sm=sz[y]; rtsz=0x3f3f3f3f; grt(y,x); int p = rrt; bt::tp = 0; insdeep(y,x,len[it]); jianli(bt::sont[p]); DC(p); fa[p] = x; sons[x].push_back(p); } } int FRT=1; void rebuild(int x) { int ff = fa[x]; ++tim; bt::node* p = bt::sont[x]; bt::sont[x]= bt::nul; fuckall(x); gsi(x,0); sm = sz[x]; rtsz=0x3f3f3f3f; grt(x,0); x = rrt; bt::sont[x]=p; zz:DC(x); if(ff)sons[ff].push_back(x); fa[x] = ff; FRT = x; } int insert(int x,int f) { bt::sont[x] = bt::nul; bt::treet[x] = bt::nul; ll ans = 0; sons[f].push_back(x); fa[x] = f; ll dd,d=0; for(int p=x;p;p=fa[p]) { dd = d; if(fa[p]) { d = bz::gdis(x,fa[p]); ans += bt::lower(bt::treet[fa[p]],r[x]-d); ans -= bt::lower(bt::sont[p],r[x]-d); bt::add(bt::sont[p],d-r[x]); } // dd = bz::gdis(x,p); bt::add(bt::treet[p],dd-r[x]); } int rere = 0; for(int p=x;fa[p];p=fa[p]) { if(bt::treet[p]->siz>bt::treet[fa[p]]->siz*0.88) rere = fa[p]; } if(rere)rebuild(rere); return ans; } } int main() { // freopen("aa.in","r",stdin); bt::init(); int ozozoz; ozozoz=_R();n=_R(); ll lastans = 0; for(int i=1;i<=n;i++) { ll A,C,R; A=_R();C=_R();R=_R(); dft::r[i] = R; A^=(int)(lastans%((long long)1e9)); if(A!=0)bz::add(i,A,C); if(A!=0)dft::adg(i,A,C); lastans += dft::insert(i,A); _W(lastans); } fwrite(pbuf,1,pp-pbuf,stdout); // cout<<JSCNT; }