[CTSC2008]网络管理
Posted Z-Y-Y-S
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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!”(全部小写不包含引号,两个单词之间有一个空格)。
输入输出样例
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]网络管理的主要内容,如果未能解决你的问题,请参考以下文章