wc2014 紫荊花之戀
阿新 • • 發佈:2019-02-20
替罪羊樹套treap,動態點分治維護
我去,分治樹連接出向下的邊沒改。。。。調了我3個小時,真是醉飛了。。。。。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; #define N 100010 #define INF 1000000000 const double Zy=0.85; int n,Root,tot,Sum,Now_root,Lim; long long Ans; struct Node{ int l,r,w,size,rnd; long long v; }t[N*150]; struct Edge{ int to,next,value; }edge[N*2],edge1[N*2]; int head[N],Tot,head1[N],Tot1; int size[N],root[N],S_root[N],f[N],A[N],fa[N][100],Floor[N]; long long dis[N][100]; bool done[N],QQQ; queue<int> Q,E; queue<int> qq; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f; } int New_edgenum() //First CK:Correct { if(!E.empty()) { int now=E.front();E.pop(); return now; } else return ++Tot1; } void Addedge(int u,int v,int w) //First CK:Correct { Tot++;edge[Tot].next=head[u];edge[Tot].to=v;edge[Tot].value=w;head[u]=Tot; Tot++;edge[Tot].next=head[v];edge[Tot].to=u;edge[Tot].value=w;head[v]=Tot; } void Addedge1(int u,int v) //First CK:Correct { int now=New_edgenum(); edge1[now].next=head1[u];edge1[now].to=v;head1[u]=now; } void Rec_treap(int &k) //First CK:Correct { if(!k)return; if(t[k].l)Rec_treap(t[k].l); if(t[k].r)Rec_treap(t[k].r); t[k].v=t[k].size=t[k].w=t[k].rnd=0; Q.push(k);k=0; } int New_node() //First CK:Correct { if(!Q.empty()) { int now=Q.front();Q.pop(); return now; } else return ++tot; } void Pushup(int k) // First CK:Correct { t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].w; } void Left_rotate(int &k) //First CK:Correct { int tmp=t[k].r;t[k].r=t[tmp].l;t[tmp].l=k; t[tmp].size=t[k].size;Pushup(k);k=tmp; } void Right_rotate(int &k) //First CK:Correct { int tmp=t[k].l;t[k].l=t[tmp].r;t[tmp].r=k; t[tmp].size=t[k].size;Pushup(k);k=tmp; } void Insert(int &k,long long x) //First CK:Correct { if(!k) { k=New_node();t[k].v=x;t[k].size=t[k].w=1; t[k].rnd=rand();return; } t[k].size++; if(t[k].v==x) t[k].w++; else if(t[k].v>x) { Insert(t[k].l,x); if(t[t[k].l].rnd<t[k].rnd)Right_rotate(k); } else { Insert(t[k].r,x); if(t[t[k].r].rnd<t[k].rnd)Left_rotate(k); } } int Query(int k,long long x) //First CK:Correct { if(!k) return 0; if(t[k].v==x) { return t[t[k].l].size+t[k].w; } else if(t[k].v>x) return Query(t[k].l,x); else return Query(t[k].r,x)+t[t[k].l].size+t[k].w; } void Find_root(int k,int last) //First CK:Correct { size[k]=1;f[k]=0; for(int i=head[k];i;i=edge[i].next) { int v=edge[i].to; if(done[v]||v==last) continue; Find_root(v,k); size[k]+=size[v]; f[k]=max(f[k],size[v]); } f[k]=max(f[k],Sum-f[k]); if(f[k]<f[Now_root]) Now_root=k; } void DFS(int k,int Fa,int rt,int floor) { Insert(root[rt],dis[k][floor]-A[k]);size[k]=1; for(int i=head[k];i;i=edge[i].next) { int v=edge[i].to; if(v==Fa||done[v]) continue; dis[v][floor]=dis[k][floor]+edge[i].value; fa[v][floor]=rt; DFS(v,k,rt,floor); size[k]+=size[v]; } } void Get_contribution(int k,int rt) { Insert(S_root[rt],dis[k][Floor[rt]-1]-A[k]); for(int i=head1[k];i;i=edge1[i].next) { int v=edge1[i].to; Get_contribution(v,rt); } } void Work(int k,int floor) { done[k]=true;Floor[k]=floor; fa[k][floor]=k;dis[k][floor]=0; DFS(k,0,k,floor); for(int i=head[k];i;i=edge[i].next) { int v=edge[i].to; if(done[v]||!v) continue; Sum=size[v];Now_root=0; Find_root(v,Now_root); Addedge1(k,Now_root); Work(Now_root,floor+1); } Get_contribution(k,k); } bool Balance(int k) { int Max=0; for(int i=head1[k];i;i=edge1[i].next) { int v=edge1[i].to; Max=max(Max,size[v]); } return Zy*size[k]>=Max; } void Rec(int k) { Rec_treap(root[k]);Rec_treap(S_root[k]); for(int i=head1[k];i;i=edge1[i].next) { int v=edge1[i].to; Rec(v); E.push(i); } head1[k]=0;done[k]=0; } void Rebuild(int k) { int FFF=fa[k][Floor[k]-1]; for(int j=head1[FFF];j;j=edge1[j].next) { int v=edge1[j].to; qq.push(v); E.push(j); } head1[FFF]=0; while(!qq.empty()) { int now=qq.front();qq.pop(); if(now!=k) Addedge1(FFF,now); } Rec(k); Now_root=0;Sum=size[k]; Find_root(k,Now_root); Addedge1(FFF,Now_root); Work(Now_root,Floor[k]); } void My_insert(int Fa,int k,int value) { int Now_floor=Floor[Fa];Floor[k]=Now_floor+1; fa[k][Floor[k]]=k;dis[k][Floor[k]]=0; if(Fa!=0) {Addedge(Fa,k,value);Addedge1(Fa,k);} for(int i=Floor[k];i>=1;i--) { int pos;long long d; if(i==Floor[k]) pos=k,d=0; else pos=fa[Fa][i],d=value+dis[Fa][i]; fa[k][i]=pos;dis[k][i]=d; size[pos]++; Insert(root[pos],d-A[k]); if(i>1) { Ans+=Query(root[fa[Fa][i-1]],(long long)A[k]-value-dis[Fa][i-1]); Ans-=Query(S_root[pos],(long long)A[k]-value-dis[Fa][i-1]); Insert(S_root[pos],(long long)value+dis[Fa][i-1]-A[k]); } } int sheep=0; for(int i=Floor[k];i>=1;i--) { int now=fa[k][i]; if(!Balance(now))sheep=now; } if(sheep)Rebuild(sheep); } int main() { int hehe=read(); n=read();f[0]=INF; for(int i=1;i<=n;i++) done[i]=true; for(int i=1;i<=n;i++) { int x=read(),y=read();A[i]=read(); x^=(Ans%1000000000); My_insert(x,i,y); printf("%lld\n",Ans); } return 0; }