很巧妙的一道题,因为是树上的操作,所以我们可以联想到树链剖分,但是存在这样的几个问题。
1.每一次查询都是查询不受影响的重要程度
2.每一个操作还可以撤回,当前的最大值在后面的操作中可能会撤回
3.懒惰标记的处理
主要就是这两个问题。
1.为了解决第一个问题,我们可以在每一次修改的时候修改当前需要修改的区间的补集,也就是说线段树维护的就是不经过改点的最大重要度,也就是该点被破坏以后不会受到影响的最大重要度
2.为了解决第二个问题,我们可以在线段树的每一个节点开一个堆,维护这一段区间的重要度。删除的话再开一个就好了。
3.这个嘛,就不要下放标记了,反正是最大值,永久化标记就好了
ps:
1.set会T,安心用堆吧
2.树剖if(size[v]>=size[son[u]])son[u]=v;因为专门构造了数据来卡,所以>会T
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#define ls u<<1,l,mid
#define rs u<<1|1,mid+1,r
#define maxn 200021
using namespace std;
priority_queue<int>s[maxn*2],nd[maxn*2];
pair<int,int>sta[maxn*2];
int n,m,top[maxn],f[maxn],cur[maxn],nu[maxn],cnt,tot=1,head[maxn];
struct PBH{int a,b,c;}P[maxn];
int size[maxn],h[maxn],son[maxn],tp;
struct edge{int v,next;}e[maxn];
void adde(int a,int b){e[tot].v=b,e[tot].next=head[a];head[a]=tot++;}
void dfs1(int u,int fa){
size[u]=1,f[u]=fa,h[u]=h[fa]+1;
for(int v,i=head[u];i;i=e[i].next){
if((v=e[i].v)==fa)continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>=size[son[u]])son[u]=v;
}
}
void dfs2(int u,int fa,int tt){
cur[nu[u]=++cnt]=u;top[u]=tt;
if(son[u])dfs2(son[u],u,tt);
for(int v,i=head[u];i;i=e[i].next){
if((v=e[i].v)==fa||v==son[u])continue;
dfs2(v,u,v);
}
}
void update(int u,int l,int r,int x,int y,int add){
if(x==l&&r==y){
if(add>0)s[u].push(add);
else nd[u].push(-add);
return ;
}int mid=l+r>>1;
if(x>mid)update(rs,x,y,add);
else if(y<=mid)update(ls,x,y,add);
else update(ls,x,mid,add),update(rs,mid+1,y,add);
}
int query(int u,int l,int r,int x){
while(!nd[u].empty()&&s[u].top()==nd[u].top())s[u].pop(),nd[u].pop();
int ans=s[u].empty() ? -1 : s[u].top();
if(l==r)return ans;
int mid=l+r>>1;
if(x>mid)ans=max(ans,query(rs,x));
else ans=max(ans,query(ls,x));
return ans;
}
int change(int a,int b,int add){
tp=0;
while(top[a]!=top[b]){
if(h[top[a]]>h[top[b]])swap(a,b);
sta[++tp]=make_pair(nu[top[b]],nu[b]);
b=f[top[b]];
}
if(h[a]>h[b])swap(a,b);
sta[++tp]=make_pair(nu[a],nu[b]);
sort(sta+1,sta+1+tp);
int last=1,now;
for(int i=1;i<=tp;i++){
now=sta[i].first-1;
if(last<=now)update(1,1,n,last,now,add);
last=sta[i].second+1;
}if(last<=n)update(1,1,n,last,n,add);
}
int main(){
scanf("%d%d",&n,&m);
for(int a,b,i=1;i<n;i++){
scanf("%d%d",&a,&b);
adde(a,b),adde(b,a);
}dfs1(1,0);dfs2(1,1,1);
int pos,a,b,c;
for(int i=1;i<=m;i++){
scanf("%d",&pos);
if(pos==0){
scanf("%d%d%d",&a,&b,&c);
P[i]=(PBH){a,b,c};
change(a,b,c);
}else if(pos==2){
scanf("%d",&a);
printf("%d\n",query(1,1,n,nu[a]));
}else{
scanf("%d",&a);
change(P[a].a,P[a].b,-P[a].c);
}
}
return 0;
}