替罪羊树套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;
}