【BZOJ4538 : [Hnoi2016]网络】树链剖分+线段树+堆

115 篇文章 0 订阅
7 篇文章 0 订阅

BZOJ4538
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发生故障时,未被影响的请求中重要度的最大值是多少?”注意可能有某个服务器自身与自身进行数据
交互的情况。2 ≤ n ≤ 10^5, 1 ≤ m ≤ 2×10^5,其他的所有输入值不超过 10^9

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

Sample Input
13 23
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
6 10
6 11
7 12
7 13
2 1
0 8 13 3
0 9 12 5
2 9
2 8
2 2
0 10 12 1
2 2
1 3
2 7
2 1
0 9 5 6
2 4
2 5
1 7
0 9 12 4
0 10 5 7
2 1
2 4
2 12
1 2
2 5
2 3
Sample Output
-1
3
5
-1
1
-1
1
1
3
6
7
7
4
6
中文题意
做法 用线段树节点维护该不经过该线段的最大值
那么你就用两个堆 插入的时候插入到第一个堆
删除的时候加入到第二个堆
每次我们查询就是第一个堆堆首如果和第二个堆堆首相同 就pop
否则查第一个
树链剖分找重儿子写>一直MLE到怀疑人生
看了下discuss 发现oier们说要写 >=
真是为oier水深火热环境堪忧

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100011;
const int MAX_M = 200011;
int fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],top[MAX_N],id[MAX_N],p[MAX_N],eid,n,ans,cnt;
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
struct priority_tree
{
    priority_queue<int> q1,q2;
    inline void push1(int x) {q1.push(x);}
    inline void push2(int x) {q2.push(x);}
    inline int top(){
        int res = -1;while(!q2.empty()&&(q1.top()==q2.top())) q1.pop(),q2.pop();
        if(!q1.empty()) res = q1.top();
        return res;
    }
}s[MAX_N<<2];
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/
void dfs1(int x,int fath)
{
    sz[x] = 1;
    fa[x] = fath;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        depth[v] = depth[x]+1;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<=sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
struct node
{
    int l,r;
    bool operator <(const node other) const
    {
        return l < other.l;
    }
}B[MAX_N];
void update(int rt,int l,int r,int x,int y,int v,int flag)
{
    if(x<=l&&r<=y)
    {
        if(flag==0) s[rt].push1(v);
        else s[rt].push2(v);
        return;
    }
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);
    else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
}
void updates(int x,int y,int c,int flag)
{
    int f1 = top[x],f2 = top[y],scnt = 0;
    while(f1!=f2)
    {
        if(depth[f1]<depth[f2])
            swap(x,y),swap(f1,f2);
        B[++scnt].r = id[x],B[scnt].l = id[f1];
        x = fa[f1];f1 = top[x];
    }
    if(depth[x]<depth[y])
        swap(x,y);
    B[++scnt].r = id[x],B[scnt].l = id[y];
    int last = 0;sort(B+1,B+1+scnt);
    for(int i = 1;i<=scnt;++i)
    {
        if(B[i].l-1>=last+1) update(1,1,n,last+1,B[i].l-1,c,flag);
        last = B[i].r;
    }
    if(n>=last+1) update(1,1,n,last+1,n,c,flag);
}
void query(int rt,int l,int r,int x)
{
    ans = max(ans,s[rt].top());
    if(l==r) return ;
    int mid = (l+r)>>1;
    if(x<=mid) query(rt<<1,l,mid,x);
    else query(rt<<1|1,mid+1,r,x);
}
/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/
struct Query{
    int x,y,v;
}Q[MAX_M];

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,b,ljq,x,y,v;
    init();
    n = read();m = read();
    for(int i = 1;i<n;++i)
    {
        a=read();b=read();
        add(a,b);add(b,a);
    }
    depth[1] = 1;dfs1(1,0);
    cnt = 0;dfs2(1,1);
    for(int i = 1;i<=m;++i)
    {
        ljq = read();
        if(ljq==0)
        {
            x = read();y =read();v=read();
            Q[i].x = x;Q[i].y = y;Q[i].v = v;
            updates(x,y,v,0);
        }
        else if(ljq==1)
        {
            v = read();
            updates(Q[v].x,Q[v].y,Q[v].v,1);
        }
        else
        {
            v = read();
            ans = -1;
            query(1,1,n,id[v]);
            printf("%d\n",ans);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值