记录编号 397426 评测结果 AAAAAAAAAA
题目名称 [HZOI 2015]榴莲 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.846 s
提交时间 2017-04-20 13:59:34 内存使用 85.17 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int n,m,w[N],head[N],next[N];
void add(int f,int t){
	static int cnt=0;
	w[++cnt]=t;
	next[cnt]=head[f];
	head[f]=cnt;
}
int fa[N],s[N],big[N],link[N],dfn[N];
void dfs(int x){
	s[x]=1;
	for (int i=head[x];i;i=next[i])
	if (!fa[w[i]]){
		int v=w[i];
		fa[v]=x;
		dfs(v);
		s[x]+=s[v];
		if (s[v]>s[big[x]]) big[x]=v;
	}
}
void po(int x){
	static int cnt=0;
	dfn[x]=++cnt;
	link[x]=(dfn[x]==dfn[fa[x]]+1?link[fa[x]]:x);
	if (!big[x]) return;
	po(big[x]);
	for (int i=head[x];i;i=next[i])
	if (w[i]!=big[x]&&w[i]!=fa[x]) po(w[i]);
}
int lca(int x,int y){
	for (;link[x]!=link[y];x=fa[link[x]])
		if (dfn[link[x]]<dfn[link[y]]) swap(x,y);
	return dfn[x]<dfn[y]?x:y;
}
struct bit{
	int a[N];
	void add(int p,int d){
		for (;p<=n;p+=p&-p) a[p]+=d;
	}
	int sum(int p){
		int ans=0;
		for (;p;p-=p&-p) ans+=a[p];
		return ans;
	}
	int sum(int l,int r){
		return sum(r)-sum(l-1);
	}
}T1,T2;
struct opt{int tp,p,d,w;bool lr;}Q[N];
int que[N],Que[N],size;
//tp=1表示在T1中[l,r]+d,tp=2表示在T2中[l,r]+d,tp=3表示询问 
int ans[N],q,tp[N],x[N],y[N],d[N];
bool cmp(int x,int y){
	return Q[x].lr==Q[y].lr?x<y:Q[x].lr<Q[y].lr;
}
void solve(int l,int r,int L,int R){
	if (l>r) return;
	if (L==R){
		for (int i=l;i<=r;i++)
			if (Q[que[i]].tp==3) ans[que[i]]=L;
		return;
	}
	int mid=(L+R)>>1,pos=l-1;
	for (int i=l;i<=r;i++){
		int id=que[i];
		int tp=Q[id].tp,p=Q[id].p,d=Q[id].d;
		if (tp==3){
			int S=T1.sum(dfn[p],dfn[p]+s[p]-1)+T2.sum(dfn[p]);
			if (S<Q[id].d) Q[id].d-=S,Q[id].lr=0,pos++;
				else Q[id].lr=1;
		}
		if (tp==1){
			if (Q[id].w>mid) T1.add(p,d),Q[id].lr=1;
			else Q[id].lr=0,pos++;
		}
		if (tp==2){
			if (Q[id].w>mid) T2.add(p,d),Q[id].lr=1;
			else Q[id].lr=0,pos++;
		}
	}
	for (int i=l;i<=r;i++){
		int id=que[i];
		if (Q[id].w<=mid) continue;
		if (Q[id].tp==1) T1.add(Q[id].p,-Q[id].d);
		if (Q[id].tp==2) T2.add(Q[id].p,-Q[id].d);
	}
	size=0;
	for (int i=l;i<=r;i++)
		if (!Q[que[i]].lr) Que[++size]=que[i];
	for (int i=l;i<=r;i++)
		if (Q[que[i]].lr) Que[++size]=que[i];
	for (int i=r;i>=l;i--) que[i]=Que[size--];
	solve(l,pos,L,mid);solve(pos+1,r,mid+1,R);
}
bool ask[N];
void push(int x,int y,int d,int w){
	int LCA=lca(x,y);
	q++;Q[q]=(opt){1,dfn[x],d,w,false};
	q++;Q[q]=(opt){1,dfn[y],d,w,false};
	q++;Q[q]=(opt){1,dfn[LCA],-d,w,false};
	if (LCA==1) return;
	q++;Q[q]=(opt){1,dfn[fa[LCA]],-d,w,false};
}
void push(int x,int d,int w){
	q++;Q[q]=(opt){2,dfn[x],d,w,false};
	q++;Q[q]=(opt){2,dfn[x]+s[x],-d,w,false};
}
int read(){
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
int main()
{
	freopen("Durio_zibethinus_Murr.in","r",stdin);
	freopen("Durio_zibethinus_Murr.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++){
		int x=read(),y=read();
		add(x,y);add(y,x);
	}
	int Max=0;
	fa[1]=1;dfs(1);po(1);
	for (int i=1;i<=m;i++){
		tp[i]=read();
		if (tp[i]==1){
			x[i]=read();y[i]=read();d[i]=read();
			push(x[i],y[i],1,d[i]);
		}
		if (tp[i]==2){
			x[i]=read();d[i]=read();
			push(x[i],1,d[i]);
		}
		if (tp[i]==3){
			int id=read();
			if (tp[id]==1) push(x[id],y[id],-1,d[id]);
				else push(x[id],-1,d[id]);
		}
		if (tp[i]==4){
			x[i]=read();d[i]=read();
			ask[++q]=1;
			Q[q]=(opt){3,x[i],d[i],false};
		}
		Max=max(Max,d[i]);
	}
	for (int i=1;i<=q;i++) que[i]=i;
	solve(1,q,0,Max);
	for (int i=1;i<=q;i++)
		if (ask[i]) printf("%d\n",ans[i]?ans[i]:-1);
	return 0;
}