【BZOJ1146】【CTSC2008】网络管理 [整体二分]
网络管理
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 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
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 }