LG P3250 [HNOI2016]网络

Description

一个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务器自身)。

由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外,每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的一种:

在某两个服务器之间出现一条新的数据交互请求;

某个数据交互结束请求;

某个服务器出现故障。系统会在任何故障发生后立即修复。也就是在出现故障的时刻之后,这个服务器依然是正常的。但在服务器产生故障时依然会对需要经过该服务器的数据交互请求造成影响。

你的任务是在每次出现故障时,维护未被影响的请求中重要度的最大值。注意,如果一个数据交互请求已经结束,则不将其纳入未被影响的请求范围。

Solution

题目要求树上不经过某个点的路径权值最大值

如果先树剖,在修改时可以在不是修改区间的区间上打标记,查询时单点查询

时间复杂度$O(n log^3 n)$

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
int n,m,head[100005],tot,siz[100005],top[100005],son[100005],dep[100005],id[100005],cnt,fa[100005];
struct Edge{
    int to,nxt;
}edge[200005];
struct Node{
    int l,r;
    bool operator <(const Node &z)const{return l==z.l?r<z.r:l<z.l;}
}node[200005];
struct DS{
    priority_queue<int>s1,s2;
    void add(int x){s1.push(x);}
    void del(int x){s2.push(x);}
    int top(){
        while(s2.size()&&s1.top()==s2.top())s1.pop(),s2.pop();
        return s1.size()?s1.top():-1;
    }
}ds[400005];
struct S{
    int a,b,v;
}sav[200005];
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
void dfs1(int k,int f){
    siz[k]=1,dep[k]=dep[f]+1,fa[k]=f;
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v!=f){
            dfs1(v,k),siz[k]+=siz[v];
            if(siz[v]>siz[son[k]])son[k]=v;
        }
    }
}
void dfs2(int k,int t){
    top[k]=t,id[k]=++cnt;
    if(son[k])dfs2(son[k],t);
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v!=fa[k]&&v!=son[k])dfs2(v,v);
    }
}
void update(int i,int l,int r,int L,int R,int v,int opt){
    if(L<=l&&r<=R){opt?ds[i].del(v):ds[i].add(v);return;}
    int mid=l+r>>1;
    if(L<=mid)update(i<<1,l,mid,L,R,v,opt);
    if(R>mid)update(i<<1|1,mid+1,r,L,R,v,opt);
}
void solve(int x,int y,int val,int opt){
    int t=0,l=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        node[++t]=(Node){id[top[x]],id[x]},x=fa[top[x]];
    }
    if(dep[x]<dep[y])swap(x,y);
    node[++t]=(Node){id[y],id[x]},sort(node+1,node+t+1);
    for(int i=1;i<=t;l=node[i++].r)if(l+1<node[i].l)update(1,1,n,l+1,node[i].l-1,val,opt);
    if(l<n)update(1,1,n,l+1,n,val,opt);
}
int query(int i,int l,int r,int p){
    if(l==r)return ds[i].top();
    int mid=l+r>>1;
    if(p<=mid)return max(ds[i].top(),query(i<<1,l,mid,p));
    else return max(ds[i].top(),query(i<<1|1,mid+1,r,p));
}
int main(){
    n=read(),m=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        edge[++tot]=(Edge){v,head[u]},head[u]=tot,edge[++tot]=(Edge){u,head[v]},head[v]=tot;
    }
    dfs1(1,0),dfs2(1,1);
    for(int i=1;i<=m;i++){
        int opt=read();
        if(!opt)sav[i]=(S){read(),read(),read()},solve(sav[i].a,sav[i].b,sav[i].v,opt);
        else if(opt==1){
            int t=read();
            solve(sav[t].a,sav[t].b,sav[t].v,opt);
        }
        else{
            int x=read();
            printf("%d
",query(1,1,n,id[x]));
        }
    }
    return 0;
}
[HNOI2016]网络
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14559437.html