记录编号 256505 评测结果 AAAAAAAAAA
题目名称 [HZOI 2015]榴莲 最终得分 100
用户昵称 GravatarAglove 是否通过 通过
代码语言 C++ 运行时间 1.674 s
提交时间 2016-04-30 21:30:56 内存使用 23.59 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;

const int maxn=100010;
int n,m,mx,u,v,k;
int h[maxn],cnt=0;
struct edge{
	int to,next;
}G[maxn<<1];
struct ASK{
	int type;
	int u,v,w,lca;
	int id,la;
}Q[maxn],Q1[maxn],Q2[maxn];
int dep[maxn],fa[maxn],anc[maxn][20];
int pos[maxn],end[maxn],tot=0;
int t[maxn];
int add[maxn<<2],sum[maxn<<2];
int tmp[maxn];
int ans[maxn];
bool cmpid(const ASK &A,const ASK &B){return A.id<B.id;}
int lowbit(int x){return x&(-x);}
void BIT_UPD(int x,int v){
	for(int i=x;i<=n;i+=lowbit(i))t[i]+=v;
}
int ask(int x){
	int sum=0;
	for(int i=x;i>=1;i-=lowbit(i))sum+=t[i];
	return sum;
}
void Add(int x,int y){
	++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;
}
void push_down(int o,int A,int B){
	int L=(o<<1),R=(L|1);
	int mid=(A+B)>>1;
	sum[L]+=(mid-A+1)*add[o];
	add[L]+=add[o];
	sum[R]+=(B-mid)*add[o];
	add[R]+=add[o];
	add[o]=0;
}
void Seg_UPD(int o,int L,int R,int x,int y,int v){
	if(L>=x&&R<=y){
		sum[o]+=(R-L+1)*v;
		add[o]+=v;
		return;
	}
	int mid=(L+R)>>1;
	if(add[o]!=0)push_down(o,L,R);
	if(y<=mid)Seg_UPD(o<<1,L,mid,x,y,v);
	else if(x>mid)Seg_UPD(o<<1|1,mid+1,R,x,y,v);
	else {Seg_UPD(o<<1,L,mid,x,y,v);Seg_UPD(o<<1|1,mid+1,R,x,y,v);}
	sum[o]=sum[o<<1]+sum[o<<1|1];
}
int Seg_ask(int o,int L,int R,int p){
	if(L==R)return sum[o];
	int mid=(L+R)>>1;
	if(add[o]!=0)push_down(o,L,R);
	if(p<=mid)return Seg_ask(o<<1,L,mid,p);
	else return Seg_ask(o<<1|1,mid+1,R,p);
}
void read(int &num){
	num=0;char ch=getchar();
	while(ch<'!')ch=getchar();
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void Get_DFS(int u,int f){
	anc[u][0]=f;fa[u]=f;pos[u]=++tot;
	for(int i=h[u];i;i=G[i].next){
		int v=G[i].to;
		if(v==f)continue;
		dep[v]=dep[u]+1;
		Get_DFS(v,u);
	}end[u]=tot;return;
}
void pre_LCA(){
	for(int i=1;i<=n;++i){
		for(int j=1;(1<<j)<=n;++j)anc[i][j]=-1;
	}
	for(int j=1;(1<<j)<=n;++j){
		for(int i=1;i<=n;++i){
			if(anc[i][j-1]!=-1){
				int a=anc[i][j-1];
				anc[i][j]=anc[a][j-1];
			}
		}
	}return;
}
int LCA(int p,int q){
	if(dep[p]<dep[q])swap(p,q);
	int log;
	for(log=0;(1<<log)<=dep[p];++log);--log;
	for(int i=log;i>=0;--i){
		if(dep[p]-(1<<i)>=dep[q])p=anc[p][i];
	}
	if(p==q)return p;
	for(int i=log;i>=0;--i){
		if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
			p=anc[p][i];q=anc[q][i];
		}
	}return fa[p];
}
void Get_back(int h,int t,int mid){
	for(int i=h;i<=t;++i){
		if(Q[i].type==1){
			if(Q[i].w>mid){
				int lca=Q[i].lca;
				BIT_UPD(pos[Q[i].u],-1);BIT_UPD(pos[Q[i].v],-1);
				BIT_UPD(pos[lca],1);
				if(fa[lca]!=-1)BIT_UPD(pos[fa[lca]],1);
			}
		}else if(Q[i].type==2){
			if(Q[i].w>mid)Seg_UPD(1,1,n,pos[Q[i].u],end[Q[i].u],-1);
		}else if(Q[i].type==3){
			if(Q[i].w>mid){
				if(Q[i].v){
					int lca=Q[i].lca;
					BIT_UPD(pos[Q[i].u],1);BIT_UPD(pos[Q[i].v],1);
					BIT_UPD(pos[lca],-1);
					if(fa[lca]!=-1)BIT_UPD(pos[fa[lca]],-1);
				}else Seg_UPD(1,1,n,pos[Q[i].u],end[Q[i].u],1);
			}
		}
	}return;
}
void Solve(int h,int t,int L,int R){
	if(h>t)return;
	if(L==R){
		for(int i=h;i<=t;++i)ans[Q[i].id]=L;
		return;
	}
	int mid=(L+R)>>1;
	for(int i=h;i<=t;++i){
		if(Q[i].type==1){
			if(Q[i].w>mid){
				int lca=Q[i].lca;
				BIT_UPD(pos[Q[i].u],1);BIT_UPD(pos[Q[i].v],1);
				BIT_UPD(pos[lca],-1);
				if(fa[lca]!=-1)BIT_UPD(pos[fa[lca]],-1);
			}
		}else if(Q[i].type==2){
			if(Q[i].w>mid)Seg_UPD(1,1,n,pos[Q[i].u],end[Q[i].u],1);
		}else if(Q[i].type==3){
			if(Q[i].w>mid){
				if(Q[i].v){
					int lca=Q[i].lca;
					BIT_UPD(pos[Q[i].u],-1);BIT_UPD(pos[Q[i].v],-1);
					BIT_UPD(pos[lca],1);
					if(fa[lca]!=-1)BIT_UPD(pos[fa[lca]],1);
				}else Seg_UPD(1,1,n,pos[Q[i].u],end[Q[i].u],-1);
			}
		}else{
			int now=ask(end[Q[i].u])-ask(pos[Q[i].u]-1);
			now+=Seg_ask(1,1,n,pos[Q[i].u]);
			tmp[i]=now;
		}
	}
	Get_back(h,t,mid);
	int l1=0,l2=0;
	for(int i=h;i<=t;++i){
		if(Q[i].type!=4){
			if(Q[i].w<=mid)Q1[++l1]=Q[i];
			else Q2[++l2]=Q[i];
		}else{
			int now=tmp[i]+Q[i].la;
			if(now<Q[i].w)Q[i].la+=tmp[i],Q1[++l1]=Q[i];
			else Q2[++l2]=Q[i];
		}
	}
	for(int i=1;i<=l1;++i)Q[i+h-1]=Q1[i];
	for(int i=1;i<=l2;++i)Q[i+h+l1-1]=Q2[i];
	Solve(h,h+l1-1,L,mid);Solve(h+l1,t,mid+1,R);
}

int main(){
	freopen("Durio_zibethinus_Murr.in","r",stdin);
	freopen("Durio_zibethinus_Murr.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<n;++i){
		read(u);read(v);
		Add(u,v);Add(v,u);
	}Get_DFS(1,-1);pre_LCA();
	for(int i=1;i<=m;++i){
		read(Q[i].type);Q[i].id=i;
		if(Q[i].type==1){
			read(Q[i].u);read(Q[i].v);read(Q[i].w);
			Q[i].lca=LCA(Q[i].u,Q[i].v);
			mx=max(mx,Q[i].w);
		}else if(Q[i].type==2){
			read(Q[i].u);read(Q[i].w);
			mx=max(mx,Q[i].w);
		}else if(Q[i].type==3){
			read(k);Q[i]=Q[k];Q[i].id=i;Q[i].type=3;
		}else read(Q[i].u),read(Q[i].w);
	}Solve(1,m,0,mx);
	sort(Q+1,Q+m+1,cmpid);
	for(int i=1;i<=m;++i){
		if(Q[i].type==4){
			if(ans[i]==0)ans[i]=-1;
			printf("%d\n",ans[i]);
		}
	}return 0;
}