[bzoj4538][HNOI2016]网络
标签: 树链剖分 线段树 优先队列
题解
这题其实用最暴力的方法就好。
直接树剖,用线段树维护不在该区间的最大权值,这个可以用堆做到(删除操作的话就再开一个堆)。
线段树有个细节,由于是区间修改,但是这个堆的话既不好合并又不好下传,我们更新直接更新到一段区间上,查询的时候就直接把这段区间的最大值跟答案取个max。(感觉自己讲的好迷,具体还是去看代码吧)
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
}
const int maxn=1e5+20;
struct node {
int v,next;
};
node e[maxn*2];
int cnt,start[maxn];
void addedge(int u,int v)
{
e[++cnt]=(node){v,start[u]};
start[u]=cnt;
}
int n,m;
int dfn[maxn],times,deep[maxn],sz[maxn],top[maxn],fa[maxn],son[maxn];
struct priority {
priority_queue <int> q1,q2;
int top()
{
while(!q1.empty() && !q2.empty() && q1.top()==q2.top())q1.pop(),q2.pop();
if(q1.empty())return 0;
return q1.top();
}
void push(int x)
{
q1.push(x);
}
void pop(int x)
{
q2.push(x);
}
bool empty()
{
while(q1.top()==q2.top())q1.pop(),q2.pop();
return q1.empty();
}
};
struct Node {
priority x;
};
Node c[maxn*4];
#define lc (o<<1)
#define rc (o<<1 | 1)
#define left lc,l,mid
#define right rc,mid+1,r
void update(int ql,int qr,int type,int d,int o,int l,int r)
{
if(ql>qr)return;
if(ql<=l && r<=qr)
{
if(type)c[o].x.push(d);
else c[o].x.pop(d);
return;
}
int mid=(l+r)>>1;
if(ql<=mid)update(ql,qr,type,d,left);
if(qr>mid)update(ql,qr,type,d,right);
}
int query(int x,int o,int l,int r)
{
if(l==r)
{
return c[o].x.top();
}
int mid=(l+r)>>1;
if(x<=mid)return max(c[o].x.top(),query(x,left));
else return max(c[o].x.top(),query(x,right));
}
void dfs(int u)
{
int Son=0;
sz[u]=1;
deep[u]=deep[fa[u]]+1;
EREP(i,u)
{
int v=e[i].v;
if(v==fa[u])continue;
fa[v]=u;
dfs(v);
sz[u]+=sz[v];
if(sz[Son]<=sz[v])Son=v;
}
son[u]=Son;
}
void dfs1(int u)
{
dfn[u]=++times;
if(son[u])
{
top[son[u]]=top[u];
dfs1(son[u]);
}
EREP(i,u)
{
int v=e[i].v;
if(v==son[u] || v==fa[u])continue;
top[v]=v;
dfs1(v);
}
}
void init()
{
n=read();m=read();
REP(i,1,n-1)
{
int u=read(),v=read();
addedge(u,v);
addedge(v,u);
}
dfs(1);
top[1]=1;
dfs1(1);
}
struct Query {
int u,v,w;
};
Query qu[maxn*2];
int dl[maxn],dr[maxn],tot,sx[maxn];
bool cmpsx(const int a,const int b)
{
return dl[a]<dl[b];
}
void change(int u,int v,int w,int type)
{
tot=0;
while(top[u]!=top[v])
{
if(deep[top[u]]<deep[top[v]])swap(u,v);
dl[++tot]=dfn[top[u]];
dr[tot]=dfn[u];
u=fa[top[u]];
}
if(deep[u]<deep[v])swap(u,v);
dl[++tot]=dfn[v],dr[tot]=dfn[u];
REP(i,1,tot)sx[i]=i;
sort(sx+1,sx+tot+1,cmpsx);
update(1,dl[sx[1]]-1,type,w,1,1,n);
REP(i,1,tot-1)
{
update(dr[sx[i]]+1,dl[sx[i+1]]-1,type,w,1,1,n);
}
update(dr[sx[tot]]+1,n,type,w,1,1,n);
}
void doing()
{
REP(i,1,m)
{
int type=read();
if(type==2)
{
int x=read(),y=query(dfn[x],1,1,n);
printf("%d
",y==0?-1:y);
}
else if(type==0)
{
int u=read(),v=read(),w=read();
qu[i]=(Query){u,v,w};
change(u,v,w,1);
}else
{
int x=read();
change(qu[x].u,qu[x].v,qu[x].w,0);
}
}
}
int main()
{
init();
doing();
return 0;
}