题目描述 Description
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。
高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。
你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:
1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。
2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
输入描述 Input Description
输入文件network.in中的第一行为两个整数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,此时路径上只有一个路由器。
输出描述 Output Description
输出文件为network.out。对于每一个第二种询问(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!
数据范围及提示 Data Size & Hint
100% 测试数据满足 n<=80000,q<=30000 。任意一个路由器在任何时刻都满足延迟时间小于108。对于所有询问满足 。
40% 测试数据满足所有询问中1<=k<=5 ,且路由器的延迟时间不会发生变化。
10% 测试数据满足n,q<=8000 。
正解:树链剖分+树状数组套主席树。
Orzywj大神写了个整体二分,代码量比我小1kb,然后常数是我的1/6。。我太弱了,所以写了个naive的树链剖分+主席树。
(其实上面这个是O(nlog^4n)的算法,所以是复杂度的差别了。。然后我后来又改了一下,直接每次把主席树的log^2n个根结点集中起来计算第k大就行了。。看下面代码吧。。)
树上的单点修改,路径查询第k大,那么显然我们可以考虑主席树。首先树剖构好这棵树,然后修改的话就用主席树修改的套路。查询的时候只要二分答案,转化为log个区间里>mid的数的个数,然后二分判定一下,就能很方便地用主席树做了。
朴素O(nlog^4n)代码:
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (80010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define lb(x) (x & -x) 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct edge{ int nt,to; }g[2*N]; 24 struct node{ int k,a,b; }q[30010]; 25 struct data{ int l,r; }qq[20]; 26 27 int head[N],top[N],fa[N],son[N],dep[N],tid[N],size[N],last[N],a[N],w[N],hsh[N+30010],n,Q,sz,ssz,num,cnt,tot; 28 int sum[200*N],ls[200*N],rs[200*N],rt[N]; 29 30 il int gi(){ 31 RG int x=0,q=1; RG char ch=getchar(); while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 32 if (ch==‘-‘) q=-1,ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return q*x; 33 } 34 35 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } 36 37 il void dfs1(RG int x,RG int p){ 38 fa[x]=p,dep[x]=dep[p]+1,size[x]=1; RG int v; 39 for (RG int i=head[x];i;i=g[i].nt){ 40 v=g[i].to; if (v==p) continue; 41 dfs1(v,x); size[x]+=size[v]; 42 if (size[son[x]]<=size[v]) son[x]=v; 43 } 44 return; 45 } 46 47 il void dfs2(RG int x,RG int p,RG int anc){ 48 top[x]=anc,tid[x]=++cnt,w[cnt]=a[x]; 49 if (son[x]) dfs2(son[x],x,anc); RG int v; 50 for (RG int i=head[x];i;i=g[i].nt){ 51 v=g[i].to; if (v==p || v==son[x]) continue; 52 dfs2(v,x,v); 53 } 54 return; 55 } 56 57 il void update(RG int x,RG int &y,RG int l,RG int r,RG int v,RG int fg){ 58 sum[y=++sz]=sum[x]+fg,ls[y]=ls[x],rs[y]=rs[x]; 59 if (l==r) return; RG int mid=(l+r)>>1; 60 if (v<=mid) update(ls[x],ls[y],l,mid,v,fg); 61 else update(rs[x],rs[y],mid+1,r,v,fg); 62 return; 63 } 64 65 il int query(RG int x,RG int l,RG int r,RG int v){ 66 if (l==r) return 0; RG int mid=(l+r)>>1; 67 if (v<=mid) return query(ls[x],l,mid,v)+sum[rs[x]]; 68 else return query(rs[x],mid+1,r,v); 69 } 70 71 il void add(RG int x,RG int v,RG int fg){ for (;x<=n;x+=lb(x)) update(rt[x],rt[x],1,tot,v,fg); return; } 72 73 il int find(RG int x,RG int key){ RG int res=0; for (;x;x-=lb(x)) res+=query(rt[x],1,tot,key); return res; } 74 75 il void change(RG int x,RG int v){ add(tid[x],last[tid[x]],-1),add(tid[x],v,1),last[tid[x]]=v; return; } 76 77 il int check(RG int key,RG int ssz,RG int k){ 78 RG int res=0; 79 for (RG int i=1;i<=ssz;++i) res+=find(qq[i].r,key)-find(qq[i].l-1,key); 80 return res<k; 81 } 82 83 il int Query(RG int u,RG int v,RG int k){ 84 RG int ssz=0,l=1,r=tot,mid,ans; 85 while (top[u]!=top[v]){ 86 if (dep[top[u]]<dep[top[v]]) swap(u,v); 87 qq[++ssz].l=tid[top[u]],qq[ssz].r=tid[u]; 88 u=fa[top[u]]; 89 } 90 if (dep[u]>dep[v]) swap(u,v); 91 qq[++ssz].l=tid[u],qq[ssz].r=tid[v]; 92 while (l<=r){ 93 mid=(l+r)>>1; 94 if (check(mid,ssz,k)) ans=mid,r=mid-1; 95 else l=mid+1; 96 } 97 return hsh[ans]; 98 } 99 100 il int lca(RG int u,RG int v){ 101 while (top[u]!=top[v]){ 102 if (dep[top[u]]<dep[top[v]]) swap(u,v); 103 u=fa[top[u]]; 104 } 105 return dep[u]<dep[v] ? u : v; 106 } 107 108 il void work(){ 109 n=gi(),Q=gi(); RG int u,v; for (RG int i=1;i<=n;++i) hsh[++tot]=a[i]=gi(); 110 for (RG int i=1;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); dfs1(1,0),dfs2(1,0,1); 111 for (RG int i=1;i<=Q;++i){ q[i].k=gi(),q[i].a=gi(),q[i].b=gi(); if (!q[i].k) hsh[++tot]=q[i].b; } 112 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 113 for (RG int i=1;i<=n;++i) w[i]=lower_bound(hsh+1,hsh+tot+1,w[i])-hsh,add(i,w[i],1),last[i]=w[i]; 114 for (RG int i=1;i<=Q;++i){ 115 if (!q[i].k) q[i].b=lower_bound(hsh+1,hsh+tot+1,q[i].b)-hsh,change(q[i].a,q[i].b); else{ 116 if (dep[q[i].a]+dep[q[i].b]-2*dep[lca(q[i].a,q[i].b)]+1<q[i].k) printf("invalid request!\n"); 117 else printf("%d\n",Query(q[i].a,q[i].b,q[i].k)); 118 } 119 } 120 return; 121 } 122 123 int main(){ 124 File("network"); 125 work(); 126 return 0; 127 }
O(nlog^3n)代码(非递归似乎快一些??):
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (80010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define lb(x) (x & -x) 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct edge{ int nt,to; }g[2*N]; 24 struct node{ int k,a,b; }q[30010]; 25 26 int head[N],top[N],fa[N],son[N],dep[N],tid[N],size[N],last[N],a[N],w[N],hsh[N+30010],n,Q,sz,num,cnt,tot; 27 int sum[200*N],ls[200*N],rs[200*N],rt[N],q1[1010],q2[1010],sz1,sz2; 28 29 il int gi(){ 30 RG int x=0,q=1; RG char ch=getchar(); while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 31 if (ch==‘-‘) q=-1,ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return q*x; 32 } 33 34 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } 35 36 il void dfs1(RG int x,RG int p){ 37 fa[x]=p,dep[x]=dep[p]+1,size[x]=1; RG int v; 38 for (RG int i=head[x];i;i=g[i].nt){ 39 v=g[i].to; if (v==p) continue; 40 dfs1(v,x); size[x]+=size[v]; 41 if (size[son[x]]<=size[v]) son[x]=v; 42 } 43 return; 44 } 45 46 il void dfs2(RG int x,RG int p,RG int anc){ 47 top[x]=anc,tid[x]=++cnt,w[cnt]=a[x]; 48 if (son[x]) dfs2(son[x],x,anc); RG int v; 49 for (RG int i=head[x];i;i=g[i].nt){ 50 v=g[i].to; if (v==p || v==son[x]) continue; 51 dfs2(v,x,v); 52 } 53 return; 54 } 55 56 il void update(RG int x,RG int &y,RG int l,RG int r,RG int v,RG int fg){ 57 sum[y=++sz]=sum[x]+fg,ls[y]=ls[x],rs[y]=rs[x]; 58 if (l==r) return; RG int mid=(l+r)>>1; 59 if (v<=mid) update(ls[x],ls[y],l,mid,v,fg); 60 else update(rs[x],rs[y],mid+1,r,v,fg); 61 return; 62 } 63 64 il int query(RG int x,RG int l,RG int r,RG int v){ 65 if (l==r) return 0; RG int mid=(l+r)>>1; 66 if (v<=mid) return query(ls[x],l,mid,v)+sum[rs[x]]; 67 else return query(rs[x],mid+1,r,v); 68 } 69 70 il int query(RG int sz1,RG int sz2,RG int l,RG int r,RG int k){ 71 if (l==r) return l; RG int mid=(l+r)>>1,res=0; 72 for (RG int i=1;i<=sz2;++i) res+=sum[rs[q2[i]]]; 73 for (RG int i=1;i<=sz1;++i) res-=sum[rs[q1[i]]]; 74 if (res<k){ 75 for (RG int i=1;i<=sz1;++i) q1[i]=ls[q1[i]]; 76 for (RG int i=1;i<=sz2;++i) q2[i]=ls[q2[i]]; 77 return query(sz1,sz2,l,mid,k-res); 78 } else{ 79 for (RG int i=1;i<=sz1;++i) q1[i]=rs[q1[i]]; 80 for (RG int i=1;i<=sz2;++i) q2[i]=rs[q2[i]]; 81 return query(sz1,sz2,mid+1,r,k); 82 } 83 } 84 85 il void add(RG int x,RG int v,RG int fg){ for (;x<=n;x+=lb(x)) update(rt[x],rt[x],1,tot,v,fg); return; } 86 87 il void change(RG int x,RG int v){ add(tid[x],last[tid[x]],-1),add(tid[x],v,1),last[tid[x]]=v; return; } 88 89 il int Query(RG int u,RG int v,RG int k){ 90 RG int sz1=0,sz2=0; 91 while (top[u]!=top[v]){ 92 if (dep[top[u]]<dep[top[v]]) swap(u,v); 93 for (RG int i=tid[top[u]]-1;i;i-=lb(i)) q1[++sz1]=rt[i]; 94 for (RG int i=tid[u];i;i-=lb(i)) q2[++sz2]=rt[i]; 95 u=fa[top[u]]; 96 } 97 if (dep[u]>dep[v]) swap(u,v); 98 for (RG int i=tid[u]-1;i;i-=lb(i)) q1[++sz1]=rt[i]; 99 for (RG int i=tid[v];i;i-=lb(i)) q2[++sz2]=rt[i]; 100 return hsh[query(sz1,sz2,1,tot,k)]; 101 } 102 103 il int lca(RG int u,RG int v){ 104 while (top[u]!=top[v]){ 105 if (dep[top[u]]<dep[top[v]]) swap(u,v); 106 u=fa[top[u]]; 107 } 108 return dep[u]<dep[v] ? u : v; 109 } 110 111 il void work(){ 112 n=gi(),Q=gi(); RG int u,v; for (RG int i=1;i<=n;++i) hsh[++tot]=a[i]=gi(); 113 for (RG int i=1;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); dfs1(1,0),dfs2(1,0,1); 114 for (RG int i=1;i<=Q;++i){ q[i].k=gi(),q[i].a=gi(),q[i].b=gi(); if (!q[i].k) hsh[++tot]=q[i].b; } 115 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 116 for (RG int i=1;i<=n;++i) w[i]=lower_bound(hsh+1,hsh+tot+1,w[i])-hsh,add(i,w[i],1),last[i]=w[i]; 117 for (RG int i=1;i<=Q;++i){ 118 if (!q[i].k) q[i].b=lower_bound(hsh+1,hsh+tot+1,q[i].b)-hsh,change(q[i].a,q[i].b); else{ 119 if (dep[q[i].a]+dep[q[i].b]-2*dep[lca(q[i].a,q[i].b)]+1<q[i].k) printf("invalid request!\n"); 120 else printf("%d\n",Query(q[i].a,q[i].b,q[i].k)); 121 } 122 } 123 return; 124 } 125 126 int main(){ 127 File("network"); 128 work(); 129 return 0; 130 }