我从未见过如此恶心的树分治。。。。
先动态维护这个树的树分治,当一个子树大小太大时,重构这个点和他的所有子树,用树分治分成平均的子树。
对于一个插入和查询,在树分治结构中从深度高到深度低遍历。然后统计新插入的点过当前中心,到当前分治结构中的路径。
对于一条从
x
到
既
dis[y]−r[y]<=r[x]−dis[x]
那么对于每个分治中心维护一个平衡树存 dis[x]−r[x] ,对于分治中心的子节点维护存h子树中 dis[x]−r[x] 的平衡树。查询时答案加当前分治中心的平衡树中 dis[y]−r[y]<=r[x]−dis[x] 的y的个数减当前分治中心有x的子树的平衡树的中 dis[y]−r[y]<=r[x]−dis[x] 的y的个数。并将这个点插入。
不知道为什么在bz上是TLE的,可能是我写的太挫。
#include <bits/stdc++.h>
using namespace std;
#define N 110000
#define M 15000000
#define ls ch[x][0]
#define rs ch[x][1]
#define ll long long
#define D 51
#define which(x) ch[fa[x]][1]==x
int n,top,r[N];
pair<int,int>st[N];
ll ans;
struct fastio
{
char getc()
{
static const int LEN = 4096;
static char buf[LEN],*S=buf,*T=buf;
if(S == T)
{
T = (S=buf)+fread(buf,1,LEN,stdin);
if(S == T)return EOF;
}
return *S++;
}
int read()
{
static char ch;
static int d;
while(!isdigit(ch=getc()));
for(d=ch-'0'; isdigit(ch=getc());)
d=(d<<3)+(d<<1)+(ch-'0');
return d;
}
}io;
struct graph
{
int head[N],nex[N<<1],to[N<<1],val[N<<1],tot;
int fa[N][21],d[N],deep[N];
void add(int x,int y,int z)
{
if(!x||!y)return;
nex[++tot]=head[x];head[x]=tot;
to[tot]=y;val[tot]=z;
if(x>y)
{
deep[x]=deep[y]+1;
fa[x][0]=y;d[x]=d[y]+z;
for(int i=1;i<=20;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
for(int i=20;i>=0;i--)
if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
if(x==y)return x;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int dis(int x,int y)
{return d[x]+d[y]-2*d[lca(x,y)];}
}g;
struct treap
{
int ch[M][2],val[M],rnd[M],size[M],fa[M],cnt;
queue<int>que;
int ap()
{
if(que.empty())return ++cnt;
int x=que.front();que.pop();
ls=rs=0;val[x]=0;rnd[x]=0;size[x]=0;fa[x]=0;
return x;
}
void pushup(int x)
{size[x]=size[ls]+size[rs]+1;}
int rotate(int x)
{
int y=fa[x],k=which(x);
ch[y][k]=ch[x][k^1];
ch[x][k^1]=y;
ch[fa[y]][which(y)]=x;
fa[x]=fa[y];fa[y]=x;
fa[ch[y][k]]=y;
pushup(y);pushup(x);
return x;
}
int insert(int x,int v)
{
if(!x)
{
size[x=ap()]=1;
val[x]=v;rnd[x]=rand()*rand();
return x;
}
if(val[x]>=v)
{
ls=insert(ls,v);
size[x]++;fa[ls]=x;
if(rnd[ls]>rnd[x])x=rotate(ls);
}
else
{
rs=insert(rs,v);
size[x]++;fa[rs]=x;
if(rnd[rs]>rnd[x])x=rotate(rs);
}
return x;
}
int query(int x,int v)
{
if(!x)return 0;
if(val[x]<=v)
return size[ls]+1+query(rs,v);
else return query(ls,v);
}
void del(int x)
{
if(!x)return;
que.push(x);
del(ls);del(rs);
}
}tr1;
struct tree_div
{
int deep[N],fa[N][D],pre[N],rt[N],rt1[N][D];
int size[N],size1[N][D],f[N],vis[N],root,sum;
int sta[N][D],tp[N],sta1[D],top1;
void init()
{
f[0]=1<<30;
for(int i=1;i<=n;i++)
vis[i]=1;
}
void ins(int x,int y)
{
for(int i=1;i<=tp[x];i++)
if(sta[x][i]==y)return;
sta[x][++tp[x]]=y;
}
void del(int x,int y,int v)
{
tr1.del(rt[x]),rt[x]=0;
top1=0;
for(int i=1,t;i<=tp[x];i++)
{
if((t=sta[x][i])>=v)
{tr1.del(rt1[x][t]);rt1[x][t]=0;}
else sta1[++top1]=t;
}
tp[x]=0;
for(int i=1;i<=top1;i++)sta[x][++tp[x]]=sta1[i];
for(int i=g.head[x];i;i=g.nex[i])
if(g.to[i]!=y&&!vis[g.to[i]])
del(g.to[i],x,v);
}
void dfs1(int x,int y,int t)
{
fa[x][deep[t]]=t;
size[x]=1;
for(int i=g.head[x];i;i=g.nex[i])
if(g.to[i]!=y&&!vis[g.to[i]])
dfs1(g.to[i],x,t),size[x]+=size[g.to[i]];
}
void dfs2(int x,int y)
{
f[x]=0;
for(int i=g.head[x];i;i=g.nex[i])
if(g.to[i]!=y&&!vis[g.to[i]])
dfs2(g.to[i],x),f[x]=max(f[x],size[g.to[i]]);
f[x]=max(f[x],sum-size[x]);
root=f[x] < f[root] ? x:root;
}
void dfs3(int x,int y,int &rt,int dis)
{
rt=tr1.insert(rt,dis-r[x]);
for(int i=g.head[x];i;i=g.nex[i])
if(g.to[i]!=y&&!vis[g.to[i]])
dfs3(g.to[i],x,rt,dis+g.val[i]);
}
void dfs4(int x,int y,int v)
{
if(deep[x]<=v)return;
vis[x]=0;
for(int i=g.head[x];i;i=g.nex[i])
if(g.to[i]!=y)
dfs4(g.to[i],x,v);
}
void rebuild(int x,int y)
{
dfs1(x,y,y);
root=0;sum=size[x];
dfs2(x,y);
pre[root]=x;deep[root]=deep[y]+1;
size[root]=sum;size1[x][deep[root]]=sum;
dfs3(root,0,rt[root],0);
vis[root]=1;
for(int t=root,i=g.head[t];i;i=g.nex[i])
if(g.to[i]!=y&&!vis[g.to[i]])
{
ins(g.to[i],deep[t]);
dfs3(g.to[i],t,rt1[g.to[i]][deep[t]],g.val[i]);
rebuild(g.to[i],t);
}
}
ll get(int x,int y,int c,int r)
{
top=0;ll ret=0;int org=x;
g.add(x,y,c);g.add(y,x,c);
deep[x]=deep[y]+1;pre[x]=x;
size[x]=1;
rt[x]=tr1.insert(rt[x],-r);
for(int i=deep[y],d=c;i>=1;i--)
{
fa[org][i]=y;
d=g.dis(org,y);
st[++top]=make_pair(x,y);
size1[x][i]++;size[y]++;
ret+=tr1.query(rt[y],r-d);
ret-=tr1.query(rt1[x][i],r-d);
rt[y]=tr1.insert(rt[y],d-r);
rt1[x][i]=tr1.insert(rt1[x][i],d-r);
ins(x,i);
x=pre[y];y=fa[x][i-1];
}
for(int i=top,t,t1,y;i>=1;i--)
if((double)size1[st[i].first][deep[st[i].second]]/size[y=st[i].second]>0.80)
{
t=fa[t1=pre[y]][deep[y]-1];
dfs4(t1,t,deep[t]);vis[t]=1;
del(t1,t,deep[y]);
rebuild(t1,t);
break;
}
return ret;
}
}tr2;
int main()
{
//freopen("ks.in","r",stdin);
//freopen("ks.out","w",stdout);
io.read();n=io.read();
tr2.init();
for(int i=1,y,c;i<=n;i++)
{
y=io.read();c=io.read();r[i]=io.read();
ans+=tr2.get(i,y=(y^ans%1000000000),c,r[i]);
printf("%lld\n",ans);
}
return 0;
}