记录编号 256223 评测结果 AAAAAAAAAA
题目名称 [HNOI 2016] 网络 最终得分 100
用户昵称 Gravatar一個人的雨 是否通过 通过
代码语言 C++ 运行时间 8.745 s
提交时间 2016-04-29 17:06:52 内存使用 107.12 MiB
显示代码纯文本
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
int n,m,tot=1,h[maxn],fa[maxn][20],dep[maxn];
struct edge{int to,next;}G[maxn*10];
struct ques{int u,v,w,id,b,opt,k,lca;}p[maxn];
int s[maxn],flag[maxn],tim=0,cle=0,st[maxn];
int ans[maxn],mx=0,tmp[maxn],en[maxn];

void add_edge(int x,int y){
	G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}

void dfs(int x,int f){
	st[x]=++tim;
	dep[x]=dep[f]+1;
	for (int i=1;i<=18;++i){
		if (dep[x]<(1<<i)) break;
		fa[x][i]=fa[fa[x][i-1]][i-1];
	}
	for (int i=h[x];i;i=G[i].next){
		int v=G[i].to;
		if (v==f) continue;
		fa[v][0]=x; dfs(v,x);
	}en[x]=tim;
}

int query(int a,int b){
    if (dep[a]<dep[b]) swap(a,b);
    int t=dep[a]-dep[b];
    for (int i=0;i<=18;++i)
       if (t&(1<<i)) a=fa[a][i];
	if (a==b) return a;
    for (int i=18;~i;i--)
       if (fa[a][i]!=fa[b][i])
           a=fa[a][i],b=fa[b][i];
    return fa[a][0];
}

int lowbit(int x){return x&-x;}

void add(int x,int v){
	for (int i=x;i<=n;i+=lowbit(i)){
		if (flag[i]!=cle) s[i]=0,flag[i]=cle;
		s[i]+=v;
	}
}

int ask(int x){
	int ret=0;
	for (int i=x;i>=1;i-=lowbit(i))
		if (flag[i]==cle) ret+=s[i];
	return ret;
}

bool cmp(const ques &a,const ques &b){
	return a.k<b.k||(a.k==b.k&&a.id<b.id);
}

void solve(int L,int R,int l,int r){
	int mid=(L+R)>>1;
	if (l>r) return;
	if (L==R){
		for (int i=l;i<=r;++i)
		    if (p[i].opt==2) ans[p[i].id]=L;
		return;
	}
	++cle; int t=l-1,num=0;
	for (int i=l;i<=r;++i){
	    if (p[i].opt==0){
			if (p[i].w>mid){
				p[i].k=1; int lca=p[i].lca; num++;
				add(st[p[i].u],1); add(st[p[i].v],1);
				add(st[lca],-1);
				if (fa[lca][0]) add(st[fa[lca][0]],-1);
			}else p[i].k=0,t++;
	    }else if (p[i].opt==1){
			if (p[i].w>mid){
				p[i].k=1; int lca=p[i].lca; num--;
				add(st[p[i].u],-1); add(st[p[i].v],-1);
				add(st[lca],1);
				if (fa[lca][0]) add(st[fa[lca][0]],1);
			}else p[i].k=0,t++;
	    }else{
			int ret=ask(en[p[i].b])-ask(st[p[i].b]-1);
			if (ret<num) p[i].k=1;
			else p[i].k=0,t++;
	    }
	}
	sort(p+l,p+r+1,cmp);
	solve(L,mid,l,t);
	solve(mid+1,R,t+1,r);
}

int main(){
	freopen("network_tenderRun.in","r",stdin);
	freopen("network_tenderRun.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;++i){
		int x,y; scanf("%d%d",&x,&y);
		add_edge(x,y); add_edge(y,x);
	}
	dfs(1,0);
	for (int i=1;i<=m;++i){
		int opt,x,y,z; p[i].id=i;
		scanf("%d",&opt); p[i].opt=opt;
		if (!opt){
			scanf("%d%d%d",&x,&y,&z);
			p[i].u=x; p[i].v=y; p[i].w=z;
			p[i].lca=query(p[i].u,p[i].v);
			mx=max(mx,z);
		}else if (opt==1){
			scanf("%d",&x); p[i]=p[x];
			p[i].opt=1; p[i].id=i;
		}else if (opt==2)scanf("%d",&p[i].b);
		tmp[i]=opt;
	}
	solve(0,mx,1,m);
    for (int i=1;i<=m;++i)
		if (tmp[i]==2) printf("%d\n",ans[i]==0?-1:ans[i]);
}