身为一个强省(HN)+强校(CJ)的蒟蒻,天天gi烂。。我还能说什么呢。
于是在一堆大佬的鼓(you)励(pian)下,去做了一下HNOI2016的网络。。。
(其实是一位名叫网管的人给我们的LCA练习题(rand的))
至于正解,当年HNOI2016考场上没有人做出正解来,所以我肯定只会打暴力。
1.首先这是一堆对于链上的操作,所以我们很容易联想到树链剖分。
2.然后要求不被影响的最大值,即不经过他的最大值,这可以想到用堆来维护。
4.因为设计删除操作,我们就可以维护一个加入堆和一个删除堆,要top的时候如果两个堆的队首相同,就一直pop;
5.运用正难则反的思想,既然维护经过他的很难的话,那我们就对树链剖分后的线段树的每个节点维护不经过他的最大值;
6.那么如何维护不经过他的呢?首先在树链剖分跳LCA的时候,把跳的那些线段全部记录下来,因为跳的这些线段都是连续的,所以我们排一遍序,取这些夹在线段中间的区间进行修改即可。
7.而查询的时候就一路查下来并不断取MAX即可;
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<set>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#define lson num<<1
#define rson num<<1|1
using namespace std;
typedef long long ll;
const int N=300050;
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
int head[N],nxt[N*2],to[N*2],dfn[N],top[N],size[N],son[N],sum,dep[N],fa[N],n,m,tt;
struct ac
{
priority_queue<int>a,d;
void push(int x) {a.push(x);}
void del(int x) {d.push(x);}
int top()
{
while(!d.empty()&&a.top()==d.top()) a.pop(),d.pop();
if(a.empty()) return -1;
return a.top();
}
}tree[N*5];
struct AC
{
int l,r;
}Data[N];
struct Ac
{
int x,y,z;
}q[N];
void dfs1(int x,int f)
{
dep[x]=dep[f]+1;size[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y!=f)
{
dfs1(y,x);
fa[y]=x;
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
}
void dfs2(int x,int f)
{
dfn[x]=++sum,top[x]=f;
if(son[x]) dfs2(son[x],f);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
}
void modify(int num,int l,int r,int L,int R,int type,int val)
{
if(L>R) return;
if(L<=l&&r<=R)
{
if(!type) tree[num].push(val);
else tree[num].del(val);
return;
}
int mid=(l+r)>>1;
if(L<=mid) modify(lson,l,mid,L,R,type,val);
if(R>mid) modify(rson,mid+1,r,L,R,type,val);
}
bool cmp(AC a,AC b)
{
return a.l<b.l;
}
void update(int x,int y,int type,int val)
{
int tot=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
Data[++tot]=(AC){dfn[top[x]],dfn[x]};x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
Data[++tot]=(AC){dfn[y],dfn[x]};
sort(Data+1,Data+1+tot,cmp);
int last=1;
for(int i=1;i<=tot;i++) modify(1,1,n,last,Data[i].l-1,type,val),last=Data[i].r+1;
modify(1,1,n,last,n,type,val);
}
int query(int num,int l,int r,int x)
{
if(l==r) return tree[num].top();
int mid=(l+r)>>1;
if(x<=mid) return max(tree[num].top(),query(lson,l,mid,x));
else return max(tree[num].top(),query(rson,mid+1,r,x));
}
int main()
{
int x,y,z,type;
n=gi(),m=gi();
for(int i=1;i<n;i++)
{
x=gi(),y=gi();
to[++tt]=y,nxt[tt]=head[x],head[x]=tt;
to[++tt]=x,nxt[tt]=head[y],head[y]=tt;
}
dfs1(1,0),dfs2(1,1);
for(int i=1;i<=m;i++)
{
type=gi();
if(type==0)
{
x=gi(),y=gi(),z=gi();
update(x,y,0,z);
q[i]=(Ac){x,y,z};
}
if(type==1)
{
x=gi();
update(q[x].x,q[x].y,1,q[x].z);
}
if(type==2)
{
x=gi();
printf("%d\n",query(1,1,n,dfn[x]));
}
}
return 0;
}