网络
特点
利用树剖+线段树+可删除堆(双堆),维护不经过某个点的最大值
具体操作
1.预处理树剖。
2.线段树每个节点一个可删除堆(两个堆)。
3.对于加边操作,树剖跳出了一个个线段,都存下来,此时这些线段表示的是这条链,那么除去这些线段表示的就是其他点。更新除这些线段以为的线段即可。
具体代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
int n,m;
struct Query {
int a,b,v;
} Qu[M*2];
vector<int>G[M];
struct Priority {
priority_queue<int>Q1,Q2;
int top() {
while(!Q1.empty()&&!Q2.empty()) {
if(Q1.top()==Q2.top())Q1.pop(),Q2.pop();
else return Q1.top();
}
if(Q1.empty())return -1;
else return Q1.top();
}
void push(int x,int tp) {
if(tp==1)Q1.push(x);
else Q2.push(x);
}
} Q[M*4];
int top[M],sz[M],dfn[M],DR[M],tot,fa[M],dep[M],son[M];
void dfs1(int x,int f) {
fa[x]=f;
son[x]=0;
dep[x]=dep[f]+1;
sz[x]=1;
for(int i=0; i<G[x].size(); i++) {
int y=G[x][i];
if(y==f)continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]])son[x]=y;
}
}
void dfs2(int x,int tp) {
top[x]=tp;
dfn[x]=++tot;
if(son[x])dfs2(son[x],tp);
for(int i=0; i<G[x].size(); i++) {
int y=G[x][i];
if(y==fa[x]||y==son[x])continue;
dfs2(y,y);
}
DR[x]=tot;
}
struct Sem {
int L,R;
void rd(int a,int b) {
L=a,R=b;
}
bool operator <(const Sem&tmp)const {
return L<tmp.L;
}
} B[M];
void update(int l,int r,int v,int tp,int L,int R,int p) {
if(l==L&&r==R) {
Q[p].push(v,tp);
return;
}
int mid=L+R>>1;
if(r<=mid)update(l,r,v,tp,L,mid,p<<1);
else if(mid<l)update(l,r,v,tp,mid+1,R,p<<1|1);
else {
update(l,mid,v,tp,L,mid,p<<1);
update(mid+1,r,v,tp,mid+1,R,p<<1|1);
}
}
void Update(int a,int b,int v,int tp) {
int len=0;
while(top[a]!=top[b]) {
if(dep[top[a]]<dep[top[b]])swap(a,b);
B[++len].rd(dfn[top[a]],dfn[a]);
a=fa[top[a]];
}
if(dep[a]>dep[b])swap(a,b);
if(dfn[a]+1<=dfn[b])B[++len].rd(dfn[a],dfn[b]);
sort(B+1,B+1+len);
B[0].R=0;
B[++len].L=n+1;
for(int i=0; i<len; i++) {
if(B[i].R+1<=B[i+1].L-1) {
update(B[i].R+1,B[i+1].L-1,v,tp,1,n,1);
}
}
}
int query(int x,int L,int R,int p) {
if(L==R)return Q[p].top();
int mid=L+R>>1;
if(x<=mid)return max(Q[p].top(),query(x,L,mid,p<<1));
else return max(Q[p].top(),query(x,mid+1,R,p<<1|1));
}
int main() {
int a,b,c,tp;
scanf("%d %d",&n,&m);
for(int i=1; i<n; i++) {
scanf("%d %d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
dfs1(1,0);
dfs2(1,1);
for(int i=1; i<=m; i++) {
scanf("%d",&tp);
if(tp==0) {
scanf("%d %d %d",&a,&b,&c);
Qu[i].a=a,Qu[i].b=b,Qu[i].v=c;
Update(a,b,c,1);
} else if(tp==1) {
scanf("%d",&a);
Update(Qu[a].a,Qu[a].b,Qu[a].v,-1);
} else {
scanf("%d",&a);
printf("%d\n",query(dfn[a],1,n,1));
}
}
return 0;
}