BZOJ1146CTSC2008网络管理 [整体二分]

Posted BearChild

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1146CTSC2008网络管理 [整体二分]相关的知识,希望对你有一定的参考价值。

网络管理

Time Limit: 50 Sec  Memory Limit: 162 MB
[Submit][Status][Discuss]

Description

  M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。
  为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。
  该网络的结构由N个路由器和N-1条高速光缆组成。
  每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。
  该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。
  高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。
  但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。
  而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。
  作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。
  该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。
  你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。
  并依次处理这Q条询问信息,它们可能是:
    1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化;
    2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

Input

  第一行为两个整数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大的路由器的延迟时间。

Output

  对于每一个第二种询问(k>0),输出一行。
  包含一个整数为相应的延迟时间。
  如果路径上的路由器不足k个,则输出信息“invalid request!”。

Sample Input

  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

Sample Output

  3
  2
  2
  invalid request!

HINT

  N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。
  对于所有询问满足0<=K<=N。

Main idea

  求树上两点路径间第k大的树,需要支持单点修改权值。

Solution

  我们一看到这道题,序列的话其实就是BZOJ1901改成求第k大。

  我们基于这个思路,从整体二分考虑,然后我们运用树链剖分线段树

  对于一个点,如果价值>=M的话就把这个点的位置+1权值,然后线段树区间求和就可以找出这个询问 在当前执行的L,M中 有几个>=M的数,由于是树结构,所以这个应该运用树链剖分来在线段树上加。

  之后跟静态查询Kth一样判断一下贡献,整体二分继续往下分治即可。

  这题思路简单,实现稍微有一点细节需要注意,算是一道经典的数据结构题。\\(≧▽≦)/

Code

  1 #include<iostream>    
  2 #include<string>    
  3 #include<algorithm>    
  4 #include<cstdio>    
  5 #include<cstring>    
  6 #include<cstdlib>    
  7 #include<cmath>    
  8 #include<map>  
  9 using namespace std;  
 10    
 11 const int ONE=160005;
 12 const int INF=1e8+1;
 13  
 14 int n,m;
 15 int x,y,k;
 16 int a[ONE];
 17 int next[ONE*2],first[ONE],go[ONE*2],tot;
 18 int Num,res,cnt;
 19 int record[ONE];
 20 int Ans[ONE];
 21  
 22 struct power
 23 {   
 24         int cnt,opt,cur;
 25         int pos,value;
 26         int l,r,k;
 27 }oper[ONE*10],qL[ONE*10],qR[ONE*10];
 28 
 29 struct point
 30 {
 31         int f,son,size,dep;
 32         int top,seg;
 33 }S[ONE];
 34 
 35 int get()
 36 {    
 37         int res=1,Q=1;char c;    
 38         while( (c=getchar())<48 || c>57 ) 
 39         if(c==\'-\')Q=-1; 
 40         res=c-48;     
 41         while( (c=getchar())>=48 && c<=57 )    
 42         res=res*10+c-48;    
 43         return res*Q;    
 44 }
 45  
 46 void Add(int u,int v)
 47 {
 48         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;
 49         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;
 50 }
 51  
 52 namespace Sgt
 53 {
 54         struct power
 55         {
 56             int value;
 57         }Node[ONE*4];
 58          
 59         void Update(int i,int l,int r,int L,int x)
 60         {
 61             if(l==r)
 62             {
 63                 Node[i].value+=x;
 64                 return;
 65             }
 66              
 67             int mid=(l+r)>>1;
 68             if(L<=mid) Update(i<<1,l,mid,L,x);
 69             else Update(i<<1|1,mid+1,r,L,x);
 70             Node[i].value=Node[i<<1].value + Node[i<<1|1].value;
 71         }
 72          
 73         void Query(int i,int l,int r,int L,int R)
 74         {
 75             if(L<=l && r<=R)
 76             {
 77                 res+=Node[i].value;
 78                 return;
 79             }
 80              
 81             int mid=(l+r)/2;
 82             if(L<=mid) Query(i<<1,l,mid,L,R);
 83             if(mid+1<=R) Query(i<<1|1,mid+1,r,L,R);
 84         }
 85 }
 86  
 87 namespace Hld
 88 {
 89         void First()
 90         {
 91             S[1].top=S[0].seg=S[1].seg=1;
 92         }
 93          
 94         void Dfs1(int u,int father)
 95         {
 96             S[u].dep=S[father].dep+1;
 97             S[u].f=father;
 98             S[u].size=1;
 99             for(int e=first[u];e;e=next[e])
100             {
101                 int v=go[e];
102                 if(v==father) continue;
103                 Dfs1(v,u);
104                 S[u].size+=S[v].size;
105                 if(S[v].size > S[S[u].son].size) S[u].son=v;
106             }   
107         }
108          
109         void Dfs2(int u,int father)
110         {
111             if(S[u].son)
112             {
113                 int v=S[u].son;
114                 S[v].top=S[u].top;
115                 S[v].seg=++S[0].seg;
116                 Dfs2(v,u);
117             }
118             for(int e=first[u];e;e=next[e])
119             {
120                 int v=go[e];
121                 if(v==father || S[u].son==v) continue;
122                 S[v].top=v;
123                 S[v].seg=++S[0].seg;
124                 Dfs2(v,u);
125             }
126         }
127          
128         void Solve(int x,int y)
129         {
130             int Tx=S[x].top,Ty=S[y].top;
131             while(Tx!=Ty)
132             {
133                 if(S[Tx].dep < S[Ty].dep)
134                 {
135                     swap(x,y);
136                     swap(Tx,Ty); 
137                 }
138                 Sgt::Query(1,1,n,S[Tx].seg,S[x].seg);
139                 x=S[Tx].f;
140                 Tx=S[x].top;
141             }
142             if(S[x].dep > S[y].dep) swap(x,y);
143             Sgt::Query(1,1,n,S[x].seg,S[y].seg);
144         }
145 }
146  
147 void Solve(int l,int r,int L,int R)//第k大
148 {
149         if(l>r) return;
150         if(L==R)
151         {
152             for(int i=l;i<=r;i++)
153             if(oper[i].opt==3)
154             Ans[oper[i].cnt] = L-1;
155             return;
156         }
157          
158         int M=(L+R)>>1;
159         
160         for(int i=l;i<=r;i++)
161         {
162             if(oper[i].opt==1 && oper[i].value>=M)
163                 Sgt::Update(1,1,n,S[oper[i].pos].seg,1);
164             if(oper[i].opt==2 && oper[i].value>=M)
165                 Sgt::Update(1,1,n,S[oper[i].pos].seg,-1);
166             if(oper[i].opt==3)
167             {
168                 res=0;
169                 Hld::Solve(oper[i].l,oper[i].r);
170                 record[i] = res;
171             }
172         }
173         
174         for(int i=l;i<=r;i++)
175         {
176             if(oper[i].opt==1 && oper[i].value>=M)
177                 Sgt::Update(1,1,n,S[oper[i].pos].seg,-1);
178             if(oper[i].opt==2 && oper[i].value>=M)
179                 Sgt::Update(1,1,n,S[oper[i].pos].seg,1);
180         }
181          
182         int l_num=0,r_num=0;
183         for(int i=l;i<=r;i++)
184         {
185             if(oper[i].opt!=3)
186             {
187                 if(oper[i].value >= M)
188                     qR[++r_num]=oper[i];
189                 else
190                     qL[++l_num]=oper[i];
191             }
192             else
193             {
194                 if(oper[i].cur + record[i] >= oper[i].k)
195                     qR[++r_num]=oper[i];
196                 else
197                 {
198                     qL[++l_num]=oper[i];
199                     qL[l_num].cur+=record[i];
200                 }
201             }
202         }
203          
204         int t=l;
205         for(int i=1;i<=l_num;i++) oper[t++]=qL[i];
206         for(int i=1;i<=r_num;i++) oper[t++]=qR[i];
207          
208         Solve(l,l+l_num-1,L,M);
209         Solve(l+l_num,r,M+1,R);
210 }
211  
212 int main() 
213 {
214         n=get();    m=get();
215         for(int i=1;i<=n;i++)
216         {
217             a[i]=get();
218             oper[++cnt].opt=1;  oper[cnt].pos=i;    oper[cnt].value=a[i];
219         }
220          
221         for(int i=1;i<n;i++)
222         {
223             x=get();    y=get();
224             Add(x,y);
225         }
226          
227         Hld::First();   
228         Hld::Dfs1(1,0); Hld::Dfs2(1,0);
229         
230         for(int i=1;i<=m;i++)
231         {
232             k=get();    x=get();    y=get();
233             if(k==0)
234             {
235                 oper[++cnt].opt=2;  oper[cnt].pos=x;    oper[cnt].value=a[x];
236                 oper[++cnt].opt=1;  oper[cnt].pos=x;    oper[cnt].value=y;
237                 a[x]=y;
238             }
239             else
240             {
241                 oper[++cnt].opt=3;  oper[cnt].l=x;  oper[cnt].r=y;  oper[cnt].k=k;
242                 oper[cnt].cnt=++Num;
243             }
244         }
245          
246         Solve(1,cnt,0,INF);
247          
248         for(int i=1;i<=Num;i++)
249         {
250             if(Ans[i]!=-1) printf("%d",Ans[i]);
251             else printf("invalid request!");
252             printf("\\n");
253         }
254 }
View Code

 

以上是关于BZOJ1146CTSC2008网络管理 [整体二分]的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1146: [CTSC2008]网络管理Network

bzoj 1146 网络管理Network (CDQ 整体二分 + 树刨)

[CTSC2008]网络管理(整体二分+树剖+树状数组)

[CTSC2008]网络管理 [整体二分]

bzoj1143 [CTSC2008]祭祀river

bzoj 1143: [CTSC2008]祭祀river