[CTSC2008] 网络管理
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。
高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。
你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:
1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。
2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
输入文件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,此时路径上只有一个路由器。
输出文件为network.out。对于每一个第二种询问(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!
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)代码:
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define N (80010)
#define il inline
#define RG register
#define ll long long
#define lb(x) (x & -x)
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to; }g[*N];
struct node{ int k,a,b; }q[];
struct data{ int l,r; }qq[]; int head[N],top[N],fa[N],son[N],dep[N],tid[N],size[N],last[N],a[N],w[N],hsh[N+],n,Q,sz,ssz,num,cnt,tot;
int sum[*N],ls[*N],rs[*N],rt[N]; il int gi(){
RG int x=,q=; RG char ch=getchar(); while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar(); while (ch>='' && ch<='') x=x*+ch-,ch=getchar(); return q*x;
} il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } il void dfs1(RG int x,RG int p){
fa[x]=p,dep[x]=dep[p]+,size[x]=; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
dfs1(v,x); size[x]+=size[v];
if (size[son[x]]<=size[v]) son[x]=v;
}
return;
} il void dfs2(RG int x,RG int p,RG int anc){
top[x]=anc,tid[x]=++cnt,w[cnt]=a[x];
if (son[x]) dfs2(son[x],x,anc); RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p || v==son[x]) continue;
dfs2(v,x,v);
}
return;
} il void update(RG int x,RG int &y,RG int l,RG int r,RG int v,RG int fg){
sum[y=++sz]=sum[x]+fg,ls[y]=ls[x],rs[y]=rs[x];
if (l==r) return; RG int mid=(l+r)>>;
if (v<=mid) update(ls[x],ls[y],l,mid,v,fg);
else update(rs[x],rs[y],mid+,r,v,fg);
return;
} il int query(RG int x,RG int l,RG int r,RG int v){
if (l==r) return ; RG int mid=(l+r)>>;
if (v<=mid) return query(ls[x],l,mid,v)+sum[rs[x]];
else return query(rs[x],mid+,r,v);
} il void add(RG int x,RG int v,RG int fg){ for (;x<=n;x+=lb(x)) update(rt[x],rt[x],,tot,v,fg); return; } il int find(RG int x,RG int key){ RG int res=; for (;x;x-=lb(x)) res+=query(rt[x],,tot,key); return res; } il void change(RG int x,RG int v){ add(tid[x],last[tid[x]],-),add(tid[x],v,),last[tid[x]]=v; return; } il int check(RG int key,RG int ssz,RG int k){
RG int res=;
for (RG int i=;i<=ssz;++i) res+=find(qq[i].r,key)-find(qq[i].l-,key);
return res<k;
} il int Query(RG int u,RG int v,RG int k){
RG int ssz=,l=,r=tot,mid,ans;
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
qq[++ssz].l=tid[top[u]],qq[ssz].r=tid[u];
u=fa[top[u]];
}
if (dep[u]>dep[v]) swap(u,v);
qq[++ssz].l=tid[u],qq[ssz].r=tid[v];
while (l<=r){
mid=(l+r)>>;
if (check(mid,ssz,k)) ans=mid,r=mid-;
else l=mid+;
}
return hsh[ans];
} il int lca(RG int u,RG int v){
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v] ? u : v;
} il void work(){
n=gi(),Q=gi(); RG int u,v; for (RG int i=;i<=n;++i) hsh[++tot]=a[i]=gi();
for (RG int i=;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); dfs1(,),dfs2(,,);
for (RG int i=;i<=Q;++i){ q[i].k=gi(),q[i].a=gi(),q[i].b=gi(); if (!q[i].k) hsh[++tot]=q[i].b; }
sort(hsh+,hsh+tot+),tot=unique(hsh+,hsh+tot+)-hsh-;
for (RG int i=;i<=n;++i) w[i]=lower_bound(hsh+,hsh+tot+,w[i])-hsh,add(i,w[i],),last[i]=w[i];
for (RG int i=;i<=Q;++i){
if (!q[i].k) q[i].b=lower_bound(hsh+,hsh+tot+,q[i].b)-hsh,change(q[i].a,q[i].b); else{
if (dep[q[i].a]+dep[q[i].b]-*dep[lca(q[i].a,q[i].b)]+<q[i].k) printf("invalid request!\n");
else printf("%d\n",Query(q[i].a,q[i].b,q[i].k));
}
}
return;
} int main(){
File("network");
work();
return ;
}
O(nlog^3n)代码(非递归似乎快一些??):
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define N (80010)
#define il inline
#define RG register
#define ll long long
#define lb(x) (x & -x)
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to; }g[*N];
struct node{ int k,a,b; }q[]; int head[N],top[N],fa[N],son[N],dep[N],tid[N],size[N],last[N],a[N],w[N],hsh[N+],n,Q,sz,num,cnt,tot;
int sum[*N],ls[*N],rs[*N],rt[N],q1[],q2[],sz1,sz2; il int gi(){
RG int x=,q=; RG char ch=getchar(); while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar(); while (ch>='' && ch<='') x=x*+ch-,ch=getchar(); return q*x;
} il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } il void dfs1(RG int x,RG int p){
fa[x]=p,dep[x]=dep[p]+,size[x]=; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
dfs1(v,x); size[x]+=size[v];
if (size[son[x]]<=size[v]) son[x]=v;
}
return;
} il void dfs2(RG int x,RG int p,RG int anc){
top[x]=anc,tid[x]=++cnt,w[cnt]=a[x];
if (son[x]) dfs2(son[x],x,anc); RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p || v==son[x]) continue;
dfs2(v,x,v);
}
return;
} il void update(RG int x,RG int &y,RG int l,RG int r,RG int v,RG int fg){
sum[y=++sz]=sum[x]+fg,ls[y]=ls[x],rs[y]=rs[x];
if (l==r) return; RG int mid=(l+r)>>;
if (v<=mid) update(ls[x],ls[y],l,mid,v,fg);
else update(rs[x],rs[y],mid+,r,v,fg);
return;
} il int query(RG int sz1,RG int sz2,RG int l,RG int r,RG int k){
if (l==r) return l; RG int mid=(l+r)>>,res=;
for (RG int i=;i<=sz2;++i) res+=sum[rs[q2[i]]];
for (RG int i=;i<=sz1;++i) res-=sum[rs[q1[i]]];
if (res<k){
for (RG int i=;i<=sz1;++i) q1[i]=ls[q1[i]];
for (RG int i=;i<=sz2;++i) q2[i]=ls[q2[i]];
return query(sz1,sz2,l,mid,k-res);
} else{
for (RG int i=;i<=sz1;++i) q1[i]=rs[q1[i]];
for (RG int i=;i<=sz2;++i) q2[i]=rs[q2[i]];
return query(sz1,sz2,mid+,r,k);
}
} il void add(RG int x,RG int v,RG int fg){ for (;x<=n;x+=lb(x)) update(rt[x],rt[x],,tot,v,fg); return; } il void change(RG int x,RG int v){ add(tid[x],last[tid[x]],-),add(tid[x],v,),last[tid[x]]=v; return; } il int Query(RG int u,RG int v,RG int k){
RG int sz1=,sz2=;
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
for (RG int i=tid[top[u]]-;i;i-=lb(i)) q1[++sz1]=rt[i];
for (RG int i=tid[u];i;i-=lb(i)) q2[++sz2]=rt[i];
u=fa[top[u]];
}
if (dep[u]>dep[v]) swap(u,v);
for (RG int i=tid[u]-;i;i-=lb(i)) q1[++sz1]=rt[i];
for (RG int i=tid[v];i;i-=lb(i)) q2[++sz2]=rt[i];
return hsh[query(sz1,sz2,,tot,k)];
} il int lca(RG int u,RG int v){
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v] ? u : v;
} il void work(){
n=gi(),Q=gi(); RG int u,v; for (RG int i=;i<=n;++i) hsh[++tot]=a[i]=gi();
for (RG int i=;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); dfs1(,),dfs2(,,);
for (RG int i=;i<=Q;++i){ q[i].k=gi(),q[i].a=gi(),q[i].b=gi(); if (!q[i].k) hsh[++tot]=q[i].b; }
sort(hsh+,hsh+tot+),tot=unique(hsh+,hsh+tot+)-hsh-;
for (RG int i=;i<=n;++i) w[i]=lower_bound(hsh+,hsh+tot+,w[i])-hsh,add(i,w[i],),last[i]=w[i];
for (RG int i=;i<=Q;++i){
if (!q[i].k) q[i].b=lower_bound(hsh+,hsh+tot+,q[i].b)-hsh,change(q[i].a,q[i].b); else{
if (dep[q[i].a]+dep[q[i].b]-*dep[lca(q[i].a,q[i].b)]+<q[i].k) printf("invalid request!\n");
else printf("%d\n",Query(q[i].a,q[i].b,q[i].k));
}
}
return;
} int main(){
File("network");
work();
return ;
}
[CTSC2008] 网络管理的更多相关文章
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- [BZOJ1146][CTSC2008]网络管理Network
[BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...
- BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 870 Solved: 299[Submit] ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- Luogu4175:[CTSC2008]网络管理Network
题面 Luogu4175:[CTSC2008]网络管理Network Sol 路径第\(k\)大 无解直接判断就好了 然后整体二分,加上树链剖分+树状数组统计 # include <bits/s ...
- BZOJ_1146_[CTSC2008]网络管理Network_主席树+树状数组
BZOJ_1146_[CTSC2008]网络管理Network_主席树 Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门 ...
- 【LG4175】[CTSC2008]网络管理
[LG4175][CTSC2008]网络管理 题面 洛谷 题解 感觉就和普通的整体二分差不太多啊... 树上修改就按时间添加,用树状数组维护一下即可 代码 #include<iostream&g ...
- 洛谷 P4175 [CTSC2008]网络管理 解题报告
P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
- 洛谷P4175 - [CTSC2008]网络管理
Portal Description 给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种: 修改一个点的点权. ...
随机推荐
- ubuntu中文输入问题
因为硬盘版的一些缺陷,我狠心的把windows8覆盖为ubuntu 13.10,用u盘安装,除了分区稀里糊涂的还不知到怎么分,其他问题就是汉字的输入问题了,因为之前选了english-US 后来就没有 ...
- idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8
问题如上面所叙: > idea中编译项目报错 java: javacTask: 源版本 1.8 需要目标版本 1.8 解决方案: > Setting->Compiler->Ja ...
- Android中的几种多线程实现
有以下几种方式: 1)Activity.runOnUiThread(Runnable) 2)View.post(Runnable) ;View.postDelay(Runnable , long) 3 ...
- Apache网页的缓存时间
配置网页缓存时间概述 通过mod_expires模块配置Apache,使网页能在客户端浏览器缓存一段时间,以避免重复请求,减轻服务端工作压力. 启用mod_expires模块后,会自动生成页面头部信息 ...
- servlet中的过滤器 国际化
1. 过滤器 基本概念 过滤器是需要在xml中配置的. 为什么需用到过滤器? 项目开发中,经常会涉及到重复代码的实现! 注册 ----à Servlet [1. 设置编码] ----à JSP 修改 ...
- 零件库管理信息系统设计--part03:管理员登录部分设计
兄弟们,我又回来啦! 上次我把表建完了.今天来点干货,我们用ssm框架来先简单实现一下管理员的登录功能. 在实现之前,我对user表(管理员表)做了些简单的修改,先来看看: 忽略哪些蓝色的马赛克和乱输 ...
- 在linux下使用百度ueditor编辑器上传图片
百度ueditor编辑器虽然强大,但是也有不足的地方.如果对ueditor流程不是很熟悉可以说走的弯路比较多,费力不讨好.下面呢,就是要解决ueditor遇到的问题. 用ueditor上传图片遇到的问 ...
- placeholder的字体样式改变,滚动条的颜色改变,ios日期兼容
placeholder:::-webkit-input-placeholder { color: rgba(153, 153, 153, 0.541);font-size:12px;}:-moz-pl ...
- vue监听滚动事件,实现滚动监听
在vue中实现滚动监听和原生js无太大差异,下面是一个简单的demo,可在控制台查看结果 <!DOCTYPE html> <html lang="en"> ...
- 机器学习:Python实现lms中的学习率的退火算法
''' 算法:lms学习率的退火算法 解决的问题:学习率不变化,收敛速度较慢的情况 思路:由初始解和控制参数初值开始,对当前解重复进行"产生新解-->计算目标函数差--> 接受或 ...