裸的树链剖分
永久化标记
数据结构居然1A感人
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
multiset<int>All;
int rt;
char c;
inline void read(int &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
#define heap priority_queue<int>
struct Data
{
heap Ad,De;
int no;
inline void Del(int A){if(A==Ad.top())Ad.pop();else De.push(A);}
inline void Add(int A){if((!De.empty())&&A==De.top())De.pop();else Ad.push(A);}
inline int da()
{
while(!De.empty())
{
if(De.top()<Ad.top())return Ad.top();
Ad.pop(),De.pop();
}
return Ad.top();
}
};
struct Seg
{
int l,r;
Data Rec;
}T[1000001];
int Dep[500001];
int HCB[500001],HCN[500001],HCP[500001],HCS[500001];
struct Chain
{
int u;
Chain *next;
}*Head[500001];
int F[500001];
int size[500001];
void DFS(int u,int f)
{
size[u]++;
Dep[u]=Dep[f]+1;
HCS[u]=0;F[u]=f;
for(Chain *tp=Head[u];tp;tp=tp->next)
if(tp->u!=f)DFS(tp->u,u),size[u]+=size[tp->u],HCS[u]=(size[HCS[u]]<size[tp->u]?tp->u:HCS[u]);
}
int tot;
void DFS(int u,int f,int B)
{
HCB[HCN[HCP[u]=++tot]=u]=B;
if(HCS[u])DFS(HCS[u],u,B);
for(Chain *tp=Head[u];tp;tp=tp->next)if(tp->u!=f&&tp->u!=HCS[u])DFS(tp->u,u,tot+1);
}
void Build(int place,int l,int r)
{
T[place].l=l,T[place].r=r;
T[place].Rec.Add(-1);
if(l==r)
return;
int lc=place<<1,mid=l+r>>1,rc=lc|1;
Build(lc,l,mid),Build(rc,mid+1,r);
}
void Add(int place,int l,int r,int delta)
{
if(T[place].l>=l&&T[place].r<=r){T[place].Rec.Add(delta);return;}
int lc=place<<1,rc=lc|1;
if(T[lc].r>=l)Add(lc,l,r,delta);
if(T[lc].r<r)Add(rc,l,r,delta);
}
void Del(int place,int l,int r,int delta)
{
if(T[place].l>=l&&T[place].r<=r){T[place].Rec.Del(delta);return;}
int lc=place<<1,rc=lc|1;
if(T[lc].r>=l)Del(lc,l,r,delta);
if(T[lc].r<r)Del(rc,l,r,delta);
}
int U[500001],V[500001],Da[500001];
int Query(int place,int l)
{
if(T[place].l==T[place].r)return T[place].Rec.da();
int lc=place<<1,rc=lc|1;
if(l<=T[lc].r)return max(Query(lc,l),T[place].Rec.da());
return max(Query(rc,l),T[place].Rec.da());
}
int Con;
struct Rt{int l,r;inline friend bool operator <(Rt a,Rt b){return a.l<b.l;}}L[200001];
int AddRuote(int l,int r){L[++Con]=(Rt){l,r};}
void MakeRuote(int no)
{
Con=0;
int u=U[no],v=V[no],deta=Da[no];
while(HCB[u]^HCB[v])
{
if(Dep[HCN[HCB[v]]]>Dep[HCN[HCB[u]]])swap(u,v);
AddRuote(HCB[u],HCP[u]);
u=F[HCN[HCB[u]]];
}
if(HCP[u]>HCP[v])swap(u,v);
AddRuote(HCP[u],HCP[v]);
}
void Add(int delta)
{
sort(L+1,L+1+Con);
if(L[1].l!=1)
Add(1,1,L[1].l-1,delta);
for(int i=2;i<=Con;i++)
Add(1,L[i-1].r+1,L[i].l-1,delta);
if(L[Con].r!=tot)Add(1,L[Con].r+1,tot,delta);
}
void Del(int delta)
{
sort(L+1,L+1+Con);
if(L[1].l!=1)
Del(1,1,L[1].l-1,delta);
for(int i=2;i<=Con;i++)
Del(1,L[i-1].r+1,L[i].l-1,delta);
if(L[Con].r!=tot)Del(1,L[Con].r+1,tot,delta);
}
inline int Query(int u)
{return Query(1,HCP[u]);}
inline void Add(int u,int v)
{
Chain *tp=new Chain;
tp->u=v,tp->next=Head[u],Head[u]=tp;
}
int n,m;
int main()
{
// freopen("std.in","r",stdin);
// freopen("self.out","w",stdout);
read(n),read(m);
int j,k;
for(int i=1;i<n;i++)
{
read(j),read(k);
Add(j,k),Add(k,j);
}
DFS(1,1);
DFS(1,1,1);
Build(1,1,tot);
int tp;
for(int i=1;i<=m;i++)
{
read(tp);
if(tp==0)
{
read(U[i]),read(V[i]),read(Da[i]);
MakeRuote(i);
Add(Da[i]);
}
else if(tp==1)
{
read(tp);
MakeRuote(tp);
Del(Da[tp]);
}
else
{
read(tp);
// int tp=Query(tp);
printf("%d\n",Query(tp));
}
}
return 0;
}