1. 程式人生 > >bzoj 4538: [Hnoi2016]網絡

bzoj 4538: [Hnoi2016]網絡

cmp queue while 請求 修復 main pri 是我 簡單

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

HINT

樣例給出的樹如下所示:

技術分享

解釋其中的部分詢問;下面的解釋中用(a,b;t,v)表示在t時刻出現的服務器a和b之間的重

要度為v的請求:

對於第一個詢問(在時刻1),此時沒有任何請求,輸出-1。

對於第四個詢問(在時刻6),此時有兩條交互(8,13;2,3),(9,12;3,5),所有詢問均經過2

號服務器,輸出-1。

對於第五個詢問(在時刻8),此時有三條交互(8,13;2,3),(9,12;3,5),(10,12;7,1),只有交互

(10,12;7,1)沒有經過2號服務器,因此輸出其重要度1。

對於最後一個詢問(在時刻23),此時有三條交互(9,5;12,6),(9,12;16,4),(10,5;17,7)。當3

號服務器出現故障時,只有交互(9,5;12,6)沒有經過3號服務器,因此輸出6。


2016.5.20新加數據一組,未重測

Source

今天翻lych博客的時候驚訝的發現他是用線段樹套堆AC的;

於是我想起了寒假的時候好不容易打出來卻MLE的悲劇,於是趕快再寫了一遍;

具體做法就是,我們對線段樹的每個節點開一個堆,如果他是詢問經過該點的,那麽我們把路徑上的節點的堆中插入v,

然而這個題是問的不經過該點的,那麽我們把這條路徑的補集區間的堆中加入v即可,每個節點的堆維護的是不經過該區間的值;

(因為鏈剖是log個區間,所以補集也是log個區間)

那麽查詢相當於就是單點查詢了,要及時和當層的堆去Max,因為這相當於是某種標記永久化;

有一個優化:

1.不用刪除堆,在全局開一個bj數組即可,可以省一半;

2.把鏈剖的size[y]>size[son[x]]改為“>="

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int N=100005;
int head[N],nxt[N<<1],to[N<<1],cnt,n,m,tot;
int size[N],son[N],dfn[N],tt,top[N],fa[N],deep[N];
bool vis[N<<1];
void lnk(int x,int y){
  to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
  to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
}
struct data{
  int x,y;
};
bool operator <(data u,data v){return u.x<v.x;} 
priority_queue<data> tr[N*4];
int Top(int x){
  while(!tr[x].empty()&&vis[tr[x].top().y]) tr[x].pop();
  if(tr[x].empty()) return -1;
  else return tr[x].top().x;
}
void dfs1(int x,int f){
  size[x]=1;deep[x]=deep[f]+1;
  for(int i=head[x];i;i=nxt[i]){
    int y=to[i];if(y==f) continue;
    dfs1(y,x);fa[y]=x;size[x]+=size[y];
    if(size[y]>=size[son[x]]) son[x]=y;
  }
}
void dfs2(int x,int f){
  top[x]=f;dfn[x]=++tt;
  if(son[x]) dfs2(son[x],f);
  for(int i=head[x];i;i=nxt[i]){
    int y=to[i];if(y==fa[x]||y==son[x]) continue;
    dfs2(y,y);
  }
}
struct Data{
  int l,r;
}q[105];
bool cmp(const Data &a,const Data &b){return a.l<b.l;}
void Lca(int x,int y){
  tot=0;
  while(top[x]!=top[y]){
    if(deep[top[x]]<deep[top[y]]) swap(x,y);
    q[++tot]=(Data){dfn[top[x]],dfn[x]};
    x=fa[top[x]];
  }
  if(deep[x]<deep[y]) swap(x,y);
  q[++tot]=(Data){dfn[y],dfn[x]};
}
void update(int x,int l,int r,int xl,int xr,int t,int v){
  if(xl>xr) return;
  if(xl<=l&&r<=xr){tr[x].push((data){v,t});return;}
  int mid=(l+r)>>1;
  if(xr<=mid) update(lson,l,mid,xl,xr,t,v);
  else if(xl>mid) update(rson,mid+1,r,xl,xr,t,v);
  else update(lson,l,mid,xl,mid,t,v),update(rson,mid+1,r,mid+1,xr,t,v);
}
void Change(int a,int b,int v,int t){
  Lca(a,b);sort(q+1,q+1+tot,cmp);
  update(1,1,n,1,q[1].l-1,t,v);
  update(1,1,n,q[tot].r+1,n,t,v);
  for(int i=2;i<=tot;i++) update(1,1,n,q[i-1].r+1,q[i].l-1,t,v);
}
int query(int x,int l,int r,int id){
  if(l==r){return Top(x);}
  int mid=(l+r)>>1;int tag=Top(x);
  if(id<=mid) return max(tag,query(lson,l,mid,id));
  else return max(tag,query(rson,mid+1,r,id));
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);lnk(x,y);}
  dfs1(1,0);dfs2(1,1);int t=0;
  while(m--){
    int type;scanf("%d",&type);t++;
    if(type==0){
      int a,b,v;scanf("%d%d%d",&a,&b,&v);
      Change(a,b,v,t);
    }
    else if(type==1){
      int t;scanf("%d",&t);vis[t]=1;
    }
    else {
      int x;scanf("%d",&x);printf("%d\n",query(1,1,n,dfn[x]));
    }
  }
  return 0;
}

bzoj 4538: [Hnoi2016]網絡