[BZOJ1146/CTSC2008]网络管理Network
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大的路由器的延迟时间。
注意N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。
对于所有询问满足0<=K<=N
Output
对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。
如果路径上的路由器不足k个,则输出信息“invalidrequest!”
(全部小写不包含引号,两个单词之间有一个空格)。
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!
一句话题意:带修改树上路径点权第k大
其实先做[Cqoi2011]动态逆序对再来看这题效果更好
这题其实可以树链剖分+线段树套平衡树+二分答案,复杂度达到了\(O(n\log^4n)\),据说能过?(反正我没写)
其实不要这么麻烦,我们直接把树剖抛弃,这样就可以达到更加优秀的复杂度
考虑不需要修改的树上路径第k大,直接用主席树,查询4条链,具体题目可以见Spoj 10628. Count on a tree
直接用主席树维护其到根的路径上的所有点,然而添加修改操作后,每次需要将子树内全部修改,复杂度达到了\(O(n\log n)\)
考虑我们能否不去修改子树,那么就可以用欧拉序来维护,在欧拉序上进行差分可以直接对子树进行修改
所以这题的做法就很明显了,树状数组套动态开点权值线段树,树状数组本质上维护dfs序的位置,在其中用线段树进行查询
复杂度\(O(n \log^2 n)\)
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
#define lowbit(x) ((x)&(-x))
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
const int N=8e4,M=2e7;
int L[N+10],R[N+10],root[(N<<1)+10],list[(N<<1)+10],v[N+10];
int n,m,T;
struct S1{
int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
int fa[N+10],top[N+10],deep[N+10],Rem[N+10],size[N+10];
int tot,Time;
void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
void insert(int x,int y){join(x,y),join(y,x);}
void dfs(int x){
deep[x]=deep[fa[x]]+1,size[x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x]) continue;
fa[son]=x,dfs(son);
size[x]+=size[son];
if (size[Rem[x]]<size[son]) Rem[x]=son;
}
}
void build(int x){
if (!x) return;
L[x]=++Time;
top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
build(Rem[x]);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x]||son==Rem[x]) continue;
build(son);
}
R[x]=Time;
}
int Lca(int x,int y){
while (top[x]!=top[y]){
if (deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return deep[x]<deep[y]?x:y;
}
}HLD;//Heavy Light Decomposition
struct S2{
int ls[M+10],rs[M+10],cnt[M+10],A[50],B[50],tot;
void Modify(int &p,int l,int r,int x,int v){
if (!p) p=++tot;
cnt[p]+=v;
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) Modify(ls[p],l,mid,x,v);
else Modify(rs[p],mid+1,r,x,v);
}
void change(int i,int x,int v){for (;i<=n;i+=lowbit(i)) Modify(root[i],1,T,x,v);}
int Query(int x,int y,int w,int v,int k){
int cntA=0,cntB=0;
for (int i=x;i;i-=lowbit(i)) A[++cntA]=root[i];
for (int i=y;i;i-=lowbit(i)) A[++cntA]=root[i];
for (int i=w;i;i-=lowbit(i)) B[++cntB]=root[i];
for (int i=v;i;i-=lowbit(i)) B[++cntB]=root[i];
int l=1,r=T;
while (l!=r){
int mid=(l+r)>>1,res=0;
for (int i=1;i<=cntA;i++) res+=cnt[rs[A[i]]];
for (int i=1;i<=cntB;i++) res-=cnt[rs[B[i]]];
if (k<=res){
for (int i=1;i<=cntA;i++) A[i]=rs[A[i]];
for (int i=1;i<=cntB;i++) B[i]=rs[B[i]];
l=mid+1;
}else{
k-=res;
for (int i=1;i<=cntA;i++) A[i]=ls[A[i]];
for (int i=1;i<=cntB;i++) B[i]=ls[B[i]];
r=mid;
}
}
return l;
}
}V_ST;//Value_Segment Tree
struct S3{
int k,x,y;
S3(){k=x=y=0;}
void rd(){k=read(),x=read(),y=read();}
}Ask[N+10];
int main(){
n=read(),m=read(); int tot=0;
for (int i=1;i<=n;i++) list[++tot]=v[i]=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
HLD.insert(x,y);
}
HLD.dfs(1),HLD.build(1);
for (int i=1;i<=m;i++){
Ask[i].rd();
if (!Ask[i].k) list[++tot]=Ask[i].y;
}
sort(list+1,list+1+tot);
T=unique(list+1,list+1+tot)-list-1;
for (int i=1;i<=n;i++) v[i]=lower_bound(list+1,list+1+T,v[i])-list;
for (int i=1;i<=m;i++) if (!Ask[i].k) Ask[i].y=lower_bound(list+1,list+1+T,Ask[i].y)-list;
for (int i=1;i<=n;i++) V_ST.change(L[i],v[i],1),V_ST.change(R[i]+1,v[i],-1);
for (int i=1;i<=m;i++){
int x=Ask[i].x,y=Ask[i].y;
if (!Ask[i].k){
V_ST.change(L[x] ,v[x],-1);
V_ST.change(R[x]+1,v[x], 1);
v[x]=y;
V_ST.change(L[x] ,v[x], 1);
V_ST.change(R[x]+1,v[x],-1);
}else{
int lca=HLD.Lca(x,y),k=Ask[i].k;
int size=HLD.deep[x]+HLD.deep[y]-2*HLD.deep[lca]+1;
if (size<k){
printf("invalid request!\n");
continue;
}
printf("%d\n",list[V_ST.Query(L[x],L[y],L[lca],L[HLD.fa[lca]],k)]);
}
}
}