题目描述 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)代码:

 //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] 网络管理的更多相关文章

  1. BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

  2. [BZOJ1146][CTSC2008]网络管理Network

    [BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...

  3. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

  4. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  5. Luogu4175:[CTSC2008]网络管理Network

    题面 Luogu4175:[CTSC2008]网络管理Network Sol 路径第\(k\)大 无解直接判断就好了 然后整体二分,加上树链剖分+树状数组统计 # include <bits/s ...

  6. BZOJ_1146_[CTSC2008]网络管理Network_主席树+树状数组

    BZOJ_1146_[CTSC2008]网络管理Network_主席树 Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门 ...

  7. 【LG4175】[CTSC2008]网络管理

    [LG4175][CTSC2008]网络管理 题面 洛谷 题解 感觉就和普通的整体二分差不太多啊... 树上修改就按时间添加,用树状数组维护一下即可 代码 #include<iostream&g ...

  8. 洛谷 P4175 [CTSC2008]网络管理 解题报告

    P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...

  9. 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树

    [BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...

  10. 洛谷P4175 - [CTSC2008]网络管理

    Portal Description 给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种: 修改一个点的点权. ...

随机推荐

  1. 有关html,css,js,less的使用规范

    写前端写久了,规则跟着开发的项目走,突然觉得是不是该总结总结前端的语言使用规则,看到下面这篇还不错,就直接链接过来了哦 http://zhibimo.com/read/Ashu/front-end-s ...

  2. Linux基础命令操作实例

    1.开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 2.使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 使用快捷键Ctrl+Alt+F2切换到终 ...

  3. SEO-发信息注意的问题

    SEO是什么? SEO的全称是Search Engine Optimization,翻译过来就是搜索引擎优化,说到搜索引擎,可能不是特别的清楚.通俗点讲,就是百度,谷歌,雅虎,这些可以直接搜索到你想要 ...

  4. SEO-百度推出新算法如何应对

    > 如何知道百度推出新算法百度推出算法的趋势> 学SEO目的做排名,长流量,赚钱> 最近一年百度搜索变动1> 2012年6月:6/22, 6/28事件,百度地震,4.5%网站被 ...

  5. TypeScript设计模式之中介者、观察者

    看看用TypeScript怎样实现常见的设计模式,顺便复习一下. 学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想 ...

  6. Solr DateRangeField

    Solr DateRangeField 是solr5.0 实现的一个feature. 关于 DateRangeField 支持日期查询如  date_field:[2016-03-23 TO 2017 ...

  7. vim 括号自动补全

    来源:http://www.cnblogs.com/huanlei/archive/2012/04/02/2430153.html 有时要重新配置vim 的,所以收藏了: inoremap ( ()& ...

  8. ehcache 使用笔记

    要想使用 java 的本地缓存,可以考虑用 ehcache,或者 guava. guava 更高端一点,可以自动定时刷新.我选择了 ehcache. 在 spring 中是集成了 ehcache 的. ...

  9. download 下载文件 IE兼容性处理

    根据CANIUSE(http://caniuse.com/#search=download)download兼容性如下图所示: 如上图所示,IE浏览器是不支持的. 1.测试代码: <!docty ...

  10. Sublime 常用快捷键

    Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W:关闭所有打开文件 Ctrl+Shift+V ...