记录编号 367580 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [WC 2014] 紫荆花之恋 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 102.511 s
提交时间 2017-01-31 18:35:59 内存使用 56.77 MiB
显示代码纯文本
#include<cstdio>
#include<set>
using namespace std;
const int N=2e5+10;
struct edge{int f,t,l;}w[N];
int T,n,c[N],head[N],tail[N],next[N];
void add(int f,int t,int l){
	static int cnt=0;
	w[++cnt]=(edge){f,t,l};
	if (!head[f]) head[f]=tail[f]=cnt;
		else tail[f]=next[tail[f]]=cnt;
	w[++cnt]=(edge){t,f,l};
	if (!head[t]) head[t]=tail[t]=cnt;
		else tail[t]=next[tail[t]]=cnt;
}
struct BST{
	struct node{
		int s,k;
		node *lc,*rc;
		node(int K){k=K;s=1;lc=rc=0;}
		node(node *x){
			s=x->s;k=x->k;
			lc=x->lc?new node(x->lc):0;
			rc=x->rc?new node(x->rc):0;
		}
		~node(){delete lc;delete rc;}
	}*root;
	void operator = (const BST x){
		clear();
		if (x.root) root=new node(x.root);
	}
	void clear(){delete root;root=0;}
	int size(node *x){return !x?0:x->s;}
	void update(node *x){x->s=size(x->lc)+size(x->rc)+1;}
	void l_rot(node *&x){
		node *y=x->rc;
		x->rc=y->lc;y->lc=x;
		update(x);update(y);
		x=y;
	}
	void r_rot(node *&x){
		node *y=x->lc;
		x->lc=y->rc;y->rc=x;
		update(x);update(y);
		x=y;
	}
	void mt(node *&x,bool y){
		if (y){
			if (!x->rc) return;
			if (size(x->rc->rc)>size(x->lc)) l_rot(x);else
			if (size(x->rc->lc)>size(x->lc))
				r_rot(x->rc),l_rot(x);
			else return;
		}
		else{
			if (!x->lc) return;
			if (size(x->lc->lc)>size(x->rc)) r_rot(x);else
			if (size(x->lc->rc)>size(x->rc))
				l_rot(x->lc),r_rot(x);
			else return;
		}
		mt(x->lc,0);mt(x->rc,1);mt(x,1),mt(x,0);
	}
	void insert(int key){insert(root,key);}
	void insert(node *&x,int key){
		if (!x){x=new node(key);return;}
		x->s++;
		insert(key>x->k?x->rc:x->lc,key);
		mt(x,key>x->k);
	}
	int rank(int key){
		int ans=0;
		for (node *x=root;x;)
			if (key>=x->k) ans+=size(x->lc)+1,x=x->rc;
				else x=x->lc;
		return ans;
	}
}Tree[N],up[N];
//分治树重构与询问 
set<int> son[N];
long long ans;
int Q[N],size,fa[N],s[N],r[N],h[N],Size[N],dep[N],dis[N][50];
void Set(int x,int Fa){
	if (fa[x]) son[fa[x]].erase(x);
	fa[x]=Fa;
	if (Fa) son[Fa].insert(x);
}
void get_sub(int x){
	Q[++size]=x;
	for (set<int>::iterator i=son[x].begin();i!=son[x].end();++i) get_sub(*i);
}
int Tree_size,Root,big[N],vis[N];
void getroot(int x,int Fa,int C){
	s[x]=1;big[x]=0;
	for (int i=head[x];i;i=next[i]){
		int v=w[i].t;
		if (v==Fa||vis[v]!=C) continue;
		getroot(v,x,C);
		s[x]+=s[v];
		if (s[v]>big[x]) big[x]=s[v];
	}
	if (s[x]>=Tree_size/2&&big[x]<=Tree_size/2) Root=x;
}
void geth(int x,int Fa,int C,BST &T,bool tp){
	if (tp) dis[x][++h[x]]=dep[x];
	T.insert(dep[x]-r[x]);s[x]=1;
	for (int i=head[x];i;i=next[i]){
		int v=w[i].t;
		if (vis[v]!=C||v==Fa) continue;
		dep[v]=dep[x]+w[i].l;
		geth(v,x,C,T,tp);
		s[x]+=s[v];
	}
}
void build(int x,int C){
	Tree[x].clear();
	dep[x]=0;
	geth(x,0,C,Tree[x],1);
	vis[x]=0;
	Size[x]=s[x];
	for (int i=head[x];i;i=next[i]){
		int v=w[i].t;
		if (vis[v]!=C) continue;
		Tree_size=s[v];
		getroot(v,0,C);
		Set(Root,x);
		up[Root].clear();
		geth(v,0,C,up[Root],0);
		build(Root,C);
	}
}
int query(int p,int D){//树上到p距离与r之差不超过D的点个数 
	int ans=0;
	for (int x=p;x;x=fa[x]){
		ans+=Tree[x].rank(D-dis[p][h[x]]);
		if (fa[x]) ans-=up[x].rank(D-dis[p][h[x]-1]);
	}
	return ans;
}
int main()
{
	freopen("flowera.in","r",stdin);
	freopen("flowera.out","w",stdout);
	scanf("%d%d",&T,&n);
	scanf("%d%d%d",&fa[1],&c[1],&r[1]);
	Size[1]=h[1]=1;Tree[1].insert(-r[1]);
	puts("0");
	for (int i=2;i<=n;i++){
		scanf("%d%d%d",&fa[i],&c[i],&r[i]);
		fa[i]^=ans%1000000000;
		add(fa[i],i,c[i]);
		ans+=query(fa[i],r[i]-c[i]);
		printf("%lld\n",ans);
		int u=fa[i];Set(i,u);
		Size[i]=1;h[i]=h[u]+1;
		for (int x=u;x;x=fa[x])
			Size[x]++,dis[i][h[x]]=dis[u][h[x]]+c[i];
		for (int x=i;x;x=fa[x]){
			Tree[x].insert(dis[i][h[x]]-r[i]);
			if (fa[x]) up[x].insert(dis[i][h[x]-1]-r[i]);
		}
		int v=0;
		for (int x=i;fa[x];x=fa[x])
			if (Size[x]>Size[fa[x]]*0.7+5) v=fa[x];
		if (v){
			size=0;get_sub(v);
			static int C=0;C++;
			int Fa=fa[v];
			for (int i=1;i<=size;i++)
				vis[Q[i]]=C,h[Q[i]]=h[Fa];
			Tree_size=size;
			getroot(v,0,C);
			up[Root]=up[v];
			Set(Root,Fa);
			build(Root,C);
		}
	}
	return 0;
}