题意:个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务器自身)。
由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外,每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的一种:
1. 在某两个服务器之间出现一条新的数据交互请求;
2. 某个数据交互结束请求;
3. 某个服务器出现故障。系统会在任何故障发生后立即修复。也就是在出现故障的时刻之后,这个服务器依然是正常的。但在服务器产生故障时依然会对需要经过该服务器的数据交互请求造成影响。
你的任务是在每次出现故障时,维护未被影响的请求中重要度的最大值。注意,如果一个数据交互请求已经结束,则不将其纳入未被影响的请求范围。
(n<=1e5,m<=2e5.)
整体二分,对于每一次二分的值(mid),把大于(mid)的边加入(如果是撤销操作,就是删除了)树状数组(这里要结合一下树的(dfn)序以及树上差分思想),然后对于一次询问,查询该点子树内的权值和,从而判断大于(mid)的经过该点的边数,如果这个数量正好等于当前树上所有大于(mid)的边数,即说明每条边都受到了影响,即无合法答案,即二分的值大了.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=2e5+5;
int n,m,tim,qtot,ans[N];
int tot,head[N],nxt[N],to[N];
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
struct query{int opt,id,x,y,z,lca;}q[N],ql[N],qr[N];
int size[N],dfn[N],f[N][21],dep[N],c[N];
inline void dfs(int u,int fa){
size[u]=1;dfn[u]=++tim;dep[u]=dep[fa]+1;f[u][0]=fa;
for(int j=1;j<=20;++j)f[u][j]=f[f[u][j-1]][j-1];
for(int i=head[u];i;i=nxt[i]){
int v=to[i];if(v==fa)continue;
dfs(v,u);size[u]+=size[v];
}
}
inline int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int j=20;j>=0;--j)
if(dep[f[x][j]]>=dep[y])x=f[x][j];
if(x==y)return x;
for(int j=20;j>=0;--j)
if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
return f[x][0];
}
inline void Add(int x,int v){if(!x)return;for(;x<=n;x+=x&-x)c[x]+=v;return;}
inline int query(int x){int cnt=0;for(;x;x-=x&-x)cnt+=c[x];return cnt;}
inline void solve(int l,int r,int st,int ed){
if(st>ed)return;
if(l==r){
for(int i=st;i<=ed;++i)if(q[i].opt==2)ans[q[i].id]=l;
return;
}
int mid=(l+r)>>1,lt=0,rt=0,now=0;
for(int i=st;i<=ed;++i){
if(!q[i].opt){
if(q[i].z>mid){
Add(dfn[q[i].x],1);Add(dfn[q[i].y],1);Add(dfn[q[i].lca],-1);Add(dfn[f[q[i].lca][0]],-1);
qr[++rt]=q[i];++now;continue;
}
if(q[i].z<=mid)ql[++lt]=q[i];continue;
}
if(q[i].opt==1){
if(q[i].z>mid){
Add(dfn[q[i].x],-1);Add(dfn[q[i].y],-1);Add(dfn[q[i].lca],1);Add(dfn[f[q[i].lca][0]],1);
qr[++rt]=q[i];--now;continue;
}
if(q[i].z<=mid)ql[++lt]=q[i];continue;
}
if(q[i].opt==2){
int sum=query(dfn[q[i].x]+size[q[i].x]-1)-query(dfn[q[i].x]-1);
if(sum==now)ql[++lt]=q[i];else qr[++rt]=q[i];
}
}
for(int i=st;i<=ed;++i){
if(!q[i].opt&&q[i].z>mid){Add(dfn[q[i].x],-1);Add(dfn[q[i].y],-1);Add(dfn[q[i].lca],1);Add(dfn[f[q[i].lca][0]],1);}
if(q[i].opt==1&&q[i].z>mid){Add(dfn[q[i].x],1);Add(dfn[q[i].y],1);Add(dfn[q[i].lca],-1);Add(dfn[f[q[i].lca][0]],-1);}
}
for(int i=1;i<=lt;++i)q[st+i-1]=ql[i];for(int i=1;i<=rt;++i)q[lt+st+i-1]=qr[i];
solve(l,mid,st,st+lt-1);solve(mid+1,r,st+lt,ed);
}
int main(){
n=read();m=read();
for(int i=1,a,b;i<n;++i)a=read(),b=read(),add(a,b),add(b,a);dfs(1,0);
for(int i=1;i<=m;++i){
q[i].opt=read();
if(!q[i].opt){q[i].x=read(),q[i].y=read(),q[i].z=read();q[i].lca=LCA(q[i].x,q[i].y);}
if(q[i].opt==1){int t=read();q[i].x=q[t].x;q[i].y=q[t].y;q[i].z=q[t].z;q[i].lca=q[t].lca;}
if(q[i].opt==2){q[i].id=++qtot;q[i].x=read();}
}
solve(-1,1e9,1,m);for(int i=1;i<=qtot;++i)printf("%d
",ans[i]);
return 0;
}