1. 程式人生 > >[CTSC2008]網絡管理

[CTSC2008]網絡管理

else 修改 root 結構 所有 rt4 能夠 行為 引號

題目描述

M公司是一個非常龐大的跨國公司,在許多國家都設有它的下屬分支機構或部門。為了讓分布在世界各地的N個部門之間協同工作,公司搭建了一個連接整個公司的通信網絡。該網絡的結構由N個路由器和N-1條高速光纜組成。每個部門都有一個專屬的路由器,部門局域網內的所有機器都聯向這個路由器,然後再通過這個通信子網與其他部門進行通信聯絡。該網絡結構保證網絡中的任意兩個路由器之間都存在一條直接或間接路徑以進行通信。 高速光纜的數據傳輸速度非常快,以至於利用光纜傳輸的延遲時間可以忽略。但是由於路由器老化,在這些路由器上進行數據交換會帶來很大的延遲。而兩個路由器之間的通信延遲時間則與這兩個路由器通信路徑上所有路由器中最大的交換延遲時間有關。作為M公司網絡部門的一名實習員工,現在要求你編寫一個簡單的程序來監視公司的網絡狀況。該程序能夠隨時更新網絡狀況的變化信息(路由器數據交換延遲時間的變化),並且根據詢問給出兩個路由器通信路徑上延遲第k大的路由器的延遲時間。

【任務】 你的程序從輸入文件中讀入N個路由器和N-1條光纜的連接信息,每個路由器初始的數據交換延遲時間Ti,以及Q條詢問(或狀態改變)的信息。並依次處理這Q條詢問信息,它們可能是:

  1. 由於更新了設備,或者設備出現新的故障,使得某個路由器的數據交換延遲時間發生了變化。

  2. 查詢某兩個路由器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
輸出樣例#1: 復制
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]網絡管理