bzoj4538 [Hnoi2016]网络

Description

  一个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做 一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务 器自身)。由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外, 每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的 管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的 一种:1.  在某两个服务器之间出现一条新的数据交互请求;2.  某个数据交互结束请求;3.  某个服务器出现故 障。系统会在任何故障发生后立即修复。也就是在出现故障的时刻之后,这个服务器依然是正常的。但在服务器产 生故障时依然会对需要经过该服务器的数据交互请求造成影响。你的任务是在每次出现故障时,维护未被影响的请 求中重要度的最大值。注意,如果一个数据交互请求已经结束,则不将其纳入未被影响的请求范围。

Input

  第一行两个正整数n,m,分别描述服务器和事件个数。服务器编号是从1开始的,因此n个服务器的编号依次是1 ,2,3,…,n。接下来n-1行,每行两个正整数u,v,描述一条树边。u和v是服务器的编号。接下来m行,按发生时刻依 次描述每一个事件;即第i行(i=1,2,3,…,m)描述时刻i发生的事件。每行的第一个数type描述事件类型,共3种 类型:(1)若type=0,之后有三个正整数a,b,v,表示服务器a,b之间出现一条重要度为v的数据交互请求;(2) 若type=1,之后有一个正整数t,表示时刻t(也就是第t个发生的事件)出现的数据交互请求结束;(3)若type=2 ,之后有一个正整数x,表示服务器x在这一时刻出现了故障。对于每个type为2的事件,就是一次询问,即询问“ 当服务器x发生故障时,未被影响的请求中重要度的最大值是多少?”注意可能有某个服务器自身与自身进行数据 交互的情况。

Output

对于每个type=2的事件,即服务器出现故障的事件,输出一行一个整数,描述未被影响的请求中重要度的最大值。如果此时没有任何请求,或者所有请求均被影响,则输出-1。

树链剖分套线段树套堆维护树上区间最大值
对于修改将路径对应的区间的补集插入或删除一个值,查询对应线段树的单点查询

最坏时间复杂度O(nlog3n)

#include<cstdio>
#include<queue>
#include<algorithm>
const int N=100005;
int es[N*2],enx[N*2],e0[N],ep=2;
int dep[N],sz[N],son[N],fa[N],top[N],id[N],idp=1;
int n,m;
void f1(int w,int pa){
    fa[w]=pa;
    dep[w]=dep[pa]+1;
    sz[w]=1;
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(u!=pa){
            f1(u,w);
            sz[w]+=sz[u];
            if(sz[u]>sz[son[w]])son[w]=u;
        }
    }
}
void f2(int w,int tp){
    top[w]=tp;
    id[w]=idp++;
    if(son[w])f2(son[w],tp);
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(u!=fa[w]&&u!=son[w])f2(u,u);
    }
}
struct heap{
    std::priority_queue<int>m,d;
    inline void ins(int x){
        m.push(x);
    }
    inline void del(int x){
        d.push(x);
    }
    inline int max(){
        while(!d.empty()&&m.top()==d.top())m.pop(),d.pop();
        if(m.empty())return -1;
        return m.top();
    }
}h[262144];
int l,r,x;
void ins(int w=1,int L=1,int R=131072){
    if(l<=L&&R<=r){
        h[w].ins(x);
        return;
    }
    int M=L+R>>1;
    if(l<=M)ins(w<<1,L,M);
    if(r>M)ins(w<<1^1,M+1,R);
}
void del(int w=1,int L=1,int R=131072){
    if(l<=L&&R<=r){
        h[w].del(x);
        return;
    }
    int M=L+R>>1;
    if(l<=M)del(w<<1,L,M);
    if(r>M)del(w<<1^1,M+1,R);
}
struct sg{int l,r;}ss[64];
bool operator<(sg a,sg b){return a.l<b.l;}
int sp;
inline void Ins(int x,int y){
    sp=0;
    ss[sp++]=(sg){0,0};
    ss[sp++]=(sg){262145,262145};
    int a=top[x],b=top[y],c;
    while(a!=b){
        if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
        ss[sp++]=(sg){id[a],id[x]};
        x=fa[a];a=top[x];
    }
    if(dep[x]<dep[y])ss[sp++]=(sg){id[x],id[y]};
    else ss[sp++]=(sg){id[y],id[x]};
    std::sort(ss,ss+sp);
    for(int i=1;i<sp;i++)if(ss[i-1].r+1<ss[i].l){
        l=ss[i-1].r+1;r=ss[i].l-1;
        ins();
    }
}
inline void Del(int x,int y){
    sp=0;
    ss[sp++]=(sg){0,0};
    ss[sp++]=(sg){262145,262145};
    int a=top[x],b=top[y],c;
    while(a!=b){
        if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
        ss[sp++]=(sg){id[a],id[x]};
        x=fa[a];a=top[x];
    }
    if(dep[x]<dep[y])ss[sp++]=(sg){id[x],id[y]};
    else ss[sp++]=(sg){id[y],id[x]};
    std::sort(ss,ss+sp);
    for(int i=1;i<sp;i++)if(ss[i-1].r+1<ss[i].l){
        l=ss[i-1].r+1;r=ss[i].l-1;
        del();
    }
}
inline void getmax(int w){
    int a=-1,b;
    for(w=id[w]+131071;w;w>>=1){
        b=h[w].max();
        if(b>a)a=b;
    }
    printf("%d
",a);
}
int qa[N*2],qb[N*2],qv[N*2];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<n;i++){
        scanf("%d%d",&a,&b);
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
    }
    f1(1,0);f2(1,1);
    for(int i=1;i<=m;i++){
        int op,a,b,v;
        scanf("%d",&op);
        if(op==0){
            scanf("%d%d%d",&a,&b,&v);
            qa[i]=a;qb[i]=b;qv[i]=v;
            x=v;
            Ins(a,b);
        }else if(op==1){
            scanf("%d",&a);
            x=qv[a];
            Del(qa[a],qb[a]);
        }else{
            scanf("%d",&v);
            getmax(v);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/5427474.html