[CTSC2008]网络管理Network
题意
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。
【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:
- 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。
- 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
N,Q<=80000
分析
一道很裸的题。
树上差分+树状数组套权值线段树,时空复杂度\(O(N \log^2 N + Q \log^2 N)\)。
细节又多又烦,写一下,调一年,入坑不花一分钱,等你来玩哦!
之前一直不知道这个继承怎么写,原来不是写继承,而是直接考虑对子树的贡献,维护前缀和加到dfs序上,查询的时候差分一下。
代码
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
#define lowbit(x) (x&-x)
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll;
co int N=8e4+1,LG=120; // log_2(1e8)->30
int n,q;
std::vector<int>vs;
// Tree Tao Tree
namespace T{
// Interval Tree
int L[N*LG],R[N*LG],sum[N*LG];
int tot,root[N];
void change(int&x,int l,int r,int p,int d){
if(!x) x=++tot;
sum[x]+=d;
if(l==r) return;
int m=(l+r)/2;
if(p<=m) change(L[x],l,m,p,d);
else change(R[x],m+1,r,p,d);
}
int query(std::vector<int>&x,int l,int r,int k){
if(l==r) return l;
int s=0;
for(int i=0;i<x.size();++i)
x[i]<0?s-=sum[R[-x[i]]]:s+=sum[R[x[i]]];
int m=(l+r)/2;
if(s>=k){
for(int i=0;i<x.size();++i)
x[i]=x[i]<0?-R[-x[i]]:R[x[i]];
return query(x,m+1,r,k);
}
else{
for(int i=0;i<x.size();++i)
x[i]=x[i]<0?-L[-x[i]]:L[x[i]];
return query(x,l,m,k-s);
}
}
// Binary Index Tree
void change(int x,int p,int d){
for(int i=x;i<=n;i+=lowbit(i))
change(root[i],1,vs.size(),p,d);
}
}
int t[N];
std::vector<int>g[N];
int fa[N],dep[N],siz[N],son[N],pos[N],dfn,top[N];
void dfs1(int x,int fa){
::fa[x]=fa,dep[x]=dep[fa]+1,siz[x]=1;
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(y==fa) continue;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int top){
pos[x]=++dfn,::top[x]=top;
if(!son[x]) return;
dfs2(son[x],top);
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(y==son[x]||y==fa[x]) continue;
dfs2(y,y);
}
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
void change(int x,int v){
T::change(pos[x],t[x],-1);
T::change(pos[x]+siz[x],t[x],1);
t[x]=v;
T::change(pos[x],v,1);
T::change(pos[x]+siz[x],v,-1);
}
void query(int x,int y,int k){
int f=lca(x,y);
if(dep[x]-dep[f]+dep[y]-dep[f]+1<k){
puts("invalid request!");
return;
}
std::vector<int> roots;
for(int i=pos[x];i;i-=lowbit(i))
roots.push_back(T::root[i]); // edit 2: root
for(int i=pos[y];i;i-=lowbit(i))
roots.push_back(T::root[i]);
for(int i=pos[f];i;i-=lowbit(i))
roots.push_back(-T::root[i]);
for(int i=pos[fa[f]];i;i-=lowbit(i))
roots.push_back(-T::root[i]);
printf("%d\n",vs[T::query(roots,1,vs.size(),k)-1]); // edit 3: back
}
struct quiz{
int k,a,b;
}Q[N];
int main(){
// freopen("BZOJ1146.in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(q);
for(int i=1;i<=n;++i)
vs.push_back(read(t[i]));
for(int i=1;i<n;++i){
int x=read<int>(),y=read<int>();
g[x].push_back(y),g[y].push_back(x);
}
for(int i=1;i<=q;++i){
read(Q[i].k),read(Q[i].a),read(Q[i].b);
if(!Q[i].k) vs.push_back(Q[i].b);
}
sort(vs.begin(),vs.end()),vs.erase(unique(vs.begin(),vs.end()),vs.end());
for(int i=1;i<=n;++i)
t[i]=lower_bound(vs.begin(),vs.end(),t[i])-vs.begin()+1; // edit 1: +1
for(int i=1;i<=q;++i)if(!Q[i].k)
Q[i].b=lower_bound(vs.begin(),vs.end(),Q[i].b)-vs.begin()+1;
dfs1(1,0),dfs2(1,1);
for(int i=1;i<=n;++i){
T::change(pos[i],t[i],1);
T::change(pos[i]+siz[i],t[i],-1);
}
for(int i=1;i<=q;++i){
if(!Q[i].k) change(Q[i].a,Q[i].b);
else query(Q[i].a,Q[i].b,Q[i].k);
}
return 0;
}