[CTSC2008]網絡管理
題目描述
M公司是一個非常龐大的跨國公司,在許多國家都設有它的下屬分支機構或部門。為了讓分布在世界各地的N個部門之間協同工作,公司搭建了一個連接整個公司的通信網絡。該網絡的結構由N個路由器和N-1條高速光纜組成。每個部門都有一個專屬的路由器,部門局域網內的所有機器都聯向這個路由器,然後再通過這個通信子網與其他部門進行通信聯絡。該網絡結構保證網絡中的任意兩個路由器之間都存在一條直接或間接路徑以進行通信。 高速光纜的數據傳輸速度非常快,以至於利用光纜傳輸的延遲時間可以忽略。但是由於路由器老化,在這些路由器上進行數據交換會帶來很大的延遲。而兩個路由器之間的通信延遲時間則與這兩個路由器通信路徑上所有路由器中最大的交換延遲時間有關。作為M公司網絡部門的一名實習員工,現在要求你編寫一個簡單的程序來監視公司的網絡狀況。該程序能夠隨時更新網絡狀況的變化信息(路由器數據交換延遲時間的變化),並且根據詢問給出兩個路由器通信路徑上延遲第k大的路由器的延遲時間。
【任務】 你的程序從輸入文件中讀入N個路由器和N-1條光纜的連接信息,每個路由器初始的數據交換延遲時間Ti,以及Q條詢問(或狀態改變)的信息。並依次處理這Q條詢問信息,它們可能是:
-
由於更新了設備,或者設備出現新的故障,使得某個路由器的數據交換延遲時間發生了變化。
-
查詢某兩個路由器a和b之間的路徑上延遲第k大的路由器的延遲時間。
輸入輸出格式
輸入格式:
第一行為兩個整數N和Q,分別表示路由器總數和詢問的總數。
第二行有N個整數,第i個數表示編號為i的路由器初始的數據延遲時間Ti。
緊接著N-1行,每行包含兩個整數x和y。表示有一條光纜連接路由器x和路由器y。
緊接著是Q行,每行三個整數k、a、b。
如果k=0,則表示路由器a的狀態發生了變化,它的數據交換延遲時間由Ta變為b。
如果k>0,則表示詢問a到b的路徑上所經過的所有路由器(包括a和b)中延遲第k大的路由器的延遲時間。註意a可以等於b,此時路徑上只有一個路由器。
輸出格式:
對於每一個第二種詢問(k>0),輸出一行。包含一個整數為相應的延遲時間。如果路徑上的路由器不足k個,則輸出信息“invalid request!”(全部小寫不包含引號,兩個單詞之間有一個空格)。
輸入輸出樣例
輸入樣例#1: 復制5 5 5 1 2 3 4 3 1 2 1 4 3 5 3 2 4 5 0 1 2 2 2 3 2 1 4 3 3 5
3 2 2 invalid request!
說明
測試數據滿足N,Q<=80000,任意一個路由器在任何時刻都滿足延遲時間小於10^8。對於所有詢問滿足0<=K<=N 。
將原樹按dfs序標號
然後按照從父親到兒子建主席樹
查詢(x,y)就是這樣:
令w=lca(x,y),h=fa(w)
對於一個數對應4顆樹(x,y,w,h)的節點(r1,r2,r3,r4),如果滿足
$c[rt1]+c[rt2]-c[rt3]-c[rt4]==k$那麽就是答案
但是修改一個點最多要更新n顆線段樹
所以用樹狀數組維護主席樹
所以查詢時,要把查詢(x,y,w,h)涉及到的線段樹的根節點編號記下來
然後二分,還是按主席樹求區間k大的套路
不過要把記下來的所有節點編號全部左移或右移
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[200001]; 11 int num,head[100001],dfn[100001],tot,size[100001],dep[100001],fa[100001][21],pos; 12 int c[48000005],ch[48000005][2],n,root[100001],N=1e8,k,cnt,t[100001],vis[100001]; 13 int now[100001],sum,q,a[100001],ans; 14 void add(int u,int v) 15 { 16 num++; 17 edge[num].next=head[u]; 18 head[u]=num; 19 edge[num].to=v; 20 } 21 void dfs(int x,int pa) 22 {int i; 23 dfn[x]=++tot; 24 size[x]=1; 25 dep[x]=dep[pa]+1; 26 for (i=1;i<=20;i++) 27 { 28 fa[x][i]=fa[fa[x][i-1]][i-1]; 29 } 30 for (i=head[x];i;i=edge[i].next) 31 { 32 int v=edge[i].to; 33 if (v==pa) continue; 34 fa[v][0]=x; 35 dfs(v,x); 36 size[x]+=size[v]; 37 } 38 } 39 int lca(int x,int y) 40 {int i; 41 if (dep[x]<dep[y]) swap(x,y); 42 for (i=20;i>=0;i--) 43 if ((1<<i)<=dep[x]-dep[y]) x=fa[x][i]; 44 if (x==y) return x; 45 for (i=20;i>=0;i--) 46 if (fa[x][i]!=fa[y][i]) 47 { 48 x=fa[x][i];y=fa[y][i]; 49 } 50 return fa[x][0]; 51 } 52 void update(int &rt,int l,int r,int x,int d) 53 { 54 if (!rt) rt=++pos; 55 c[rt]+=d; 56 if (l==r) return; 57 int mid=(l+r)/2; 58 if (x<=mid) 59 update(ch[rt][0],l,mid,x,d); 60 else update(ch[rt][1],mid+1,r,x,d); 61 } 62 void add(int x,int d,int f) 63 { 64 while (x<=n) 65 { 66 update(root[x],0,N,d,f); 67 x+=(x&(-x)); 68 } 69 } 70 int query(int x,int y,int w,int h) 71 {int i; 72 if (dep[x]-dep[w]+dep[y]-dep[h]<k) 73 return -1; 74 k=dep[x]+dep[y]-dep[w]-dep[h]-k+1; 75 if (k<=0) return -1; 76 x=dfn[x];y=dfn[y];w=dfn[w];h=dfn[h]; 77 cnt=0; 78 for (i=x;i;i-=(i&(-i))) 79 { 80 if (vis[i]) continue; 81 t[++cnt]=i; 82 vis[i]=1; 83 } 84 for (i=y;i;i-=(i&(-i))) 85 { 86 if (vis[i]) continue; 87 t[++cnt]=i; 88 vis[i]=1; 89 } 90 for (i=w;i;i-=(i&(-i))) 91 { 92 if (vis[i]) continue; 93 t[++cnt]=i; 94 vis[i]=1; 95 } 96 for (i=h;i;i-=(i&(-i))) 97 { 98 if (vis[i]) continue; 99 t[++cnt]=i; 100 vis[i]=1; 101 } 102 for (i=1;i<=cnt;i++) 103 now[t[i]]=root[t[i]]; 104 int l=0,r=N; 105 while (l<r) 106 { 107 sum=0; 108 for (i=x;i;i-=(i&(-i))) 109 sum+=c[ch[now[i]][0]]; 110 for (i=y;i;i-=(i&(-i))) 111 sum+=c[ch[now[i]][0]]; 112 for (i=w;i;i-=(i&(-i))) 113 sum-=c[ch[now[i]][0]]; 114 for (i=h;i;i-=(i&(-i))) 115 sum-=c[ch[now[i]][0]]; 116 int mid=(l+r)/2; 117 if (sum<k) 118 { 119 k-=sum;l=mid+1; 120 for (i=1;i<=cnt;i++) 121 now[t[i]]=ch[now[t[i]]][1]; 122 } 123 else 124 { 125 r=mid; 126 for (i=1;i<=cnt;i++) 127 now[t[i]]=ch[now[t[i]]][0]; 128 } 129 } 130 for (i=1;i<=cnt;i++) 131 vis[t[i]]=0; 132 return l; 133 } 134 int main() 135 {int i,x,y,u,v; 136 cin>>n>>q; 137 for (i=1;i<=n;i++) 138 { 139 scanf("%d",&a[i]); 140 } 141 for (i=1;i<=n-1;i++) 142 { 143 scanf("%d%d",&u,&v); 144 add(u,v);add(v,u); 145 } 146 dfs(1,0); 147 for (i=1;i<=n;i++) 148 { 149 add(dfn[i],a[i],1); 150 add(dfn[i]+size[i],a[i],-1); 151 } 152 while (q--) 153 { 154 scanf("%d%d%d",&k,&x,&y); 155 if (k==0) 156 { 157 add(dfn[x],a[x],-1); 158 add(dfn[x]+size[x],a[x],1); 159 add(dfn[x],y,1); 160 add(dfn[x]+size[x],y,-1); 161 a[x]=y; 162 } 163 else 164 { 165 int w=lca(x,y),h=fa[w][0]; 166 ans=query(x,y,w,h); 167 if (ans!=-1) 168 printf("%d\n",ans); 169 else 170 printf("invalid request!\n"); 171 } 172 } 173 }
[CTSC2008]網絡管理