【BZOJ1146】【CTSC2008】网络管理 [整体二分]
网络管理
Time Limit: 50 Sec Memory Limit: 162 MB
[Submit][Status][Discuss]
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大的路由器的延迟时间。
Output
对于每一个第二种询问(k>0),输出一行。
包含一个整数为相应的延迟时间。
如果路径上的路由器不足k个,则输出信息“invalid request!”。
Sample Input
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
2
2
invalid request!
HINT
N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。
对于所有询问满足0<=K<=N。
Main idea
求树上两点路径间第k大的树,需要支持单点修改权值。
Solution
我们一看到这道题,序列的话其实就是BZOJ1901改成求第k大。
我们基于这个思路,从整体二分考虑,然后我们运用树链剖分和线段树。
对于一个点,如果价值>=M的话就把这个点的位置+1权值,然后线段树区间求和就可以找出这个询问 在当前执行的L,M中 有几个>=M的数,由于是树结构,所以这个应该运用树链剖分来在线段树上加。
之后跟静态查询Kth一样判断一下贡献,整体二分继续往下分治即可。
这题思路简单,实现稍微有一点细节需要注意,算是一道经典的数据结构题。\(≧▽≦)/
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<map>
using namespace std; const int ONE=;
const int INF=1e8+; int n,m;
int x,y,k;
int a[ONE];
int next[ONE*],first[ONE],go[ONE*],tot;
int Num,res,cnt;
int record[ONE];
int Ans[ONE]; struct power
{
int cnt,opt,cur;
int pos,value;
int l,r,k;
}oper[ONE*],qL[ONE*],qR[ONE*]; struct point
{
int f,son,size,dep;
int top,seg;
}S[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Add(int u,int v)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v;
next[++tot]=first[v]; first[v]=tot; go[tot]=u;
} namespace Sgt
{
struct power
{
int value;
}Node[ONE*]; void Update(int i,int l,int r,int L,int x)
{
if(l==r)
{
Node[i].value+=x;
return;
} int mid=(l+r)>>;
if(L<=mid) Update(i<<,l,mid,L,x);
else Update(i<<|,mid+,r,L,x);
Node[i].value=Node[i<<].value + Node[i<<|].value;
} void Query(int i,int l,int r,int L,int R)
{
if(L<=l && r<=R)
{
res+=Node[i].value;
return;
} int mid=(l+r)/;
if(L<=mid) Query(i<<,l,mid,L,R);
if(mid+<=R) Query(i<<|,mid+,r,L,R);
}
} namespace Hld
{
void First()
{
S[].top=S[].seg=S[].seg=;
} void Dfs1(int u,int father)
{
S[u].dep=S[father].dep+;
S[u].f=father;
S[u].size=;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father) continue;
Dfs1(v,u);
S[u].size+=S[v].size;
if(S[v].size > S[S[u].son].size) S[u].son=v;
}
} void Dfs2(int u,int father)
{
if(S[u].son)
{
int v=S[u].son;
S[v].top=S[u].top;
S[v].seg=++S[].seg;
Dfs2(v,u);
}
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || S[u].son==v) continue;
S[v].top=v;
S[v].seg=++S[].seg;
Dfs2(v,u);
}
} void Solve(int x,int y)
{
int Tx=S[x].top,Ty=S[y].top;
while(Tx!=Ty)
{
if(S[Tx].dep < S[Ty].dep)
{
swap(x,y);
swap(Tx,Ty);
}
Sgt::Query(,,n,S[Tx].seg,S[x].seg);
x=S[Tx].f;
Tx=S[x].top;
}
if(S[x].dep > S[y].dep) swap(x,y);
Sgt::Query(,,n,S[x].seg,S[y].seg);
}
} void Solve(int l,int r,int L,int R)//第k大
{
if(l>r) return;
if(L==R)
{
for(int i=l;i<=r;i++)
if(oper[i].opt==)
Ans[oper[i].cnt] = L-;
return;
} int M=(L+R)>>; for(int i=l;i<=r;i++)
{
if(oper[i].opt== && oper[i].value>=M)
Sgt::Update(,,n,S[oper[i].pos].seg,);
if(oper[i].opt== && oper[i].value>=M)
Sgt::Update(,,n,S[oper[i].pos].seg,-);
if(oper[i].opt==)
{
res=;
Hld::Solve(oper[i].l,oper[i].r);
record[i] = res;
}
} for(int i=l;i<=r;i++)
{
if(oper[i].opt== && oper[i].value>=M)
Sgt::Update(,,n,S[oper[i].pos].seg,-);
if(oper[i].opt== && oper[i].value>=M)
Sgt::Update(,,n,S[oper[i].pos].seg,);
} int l_num=,r_num=;
for(int i=l;i<=r;i++)
{
if(oper[i].opt!=)
{
if(oper[i].value >= M)
qR[++r_num]=oper[i];
else
qL[++l_num]=oper[i];
}
else
{
if(oper[i].cur + record[i] >= oper[i].k)
qR[++r_num]=oper[i];
else
{
qL[++l_num]=oper[i];
qL[l_num].cur+=record[i];
}
}
} int t=l;
for(int i=;i<=l_num;i++) oper[t++]=qL[i];
for(int i=;i<=r_num;i++) oper[t++]=qR[i]; Solve(l,l+l_num-,L,M);
Solve(l+l_num,r,M+,R);
} int main()
{
n=get(); m=get();
for(int i=;i<=n;i++)
{
a[i]=get();
oper[++cnt].opt=; oper[cnt].pos=i; oper[cnt].value=a[i];
} for(int i=;i<n;i++)
{
x=get(); y=get();
Add(x,y);
} Hld::First();
Hld::Dfs1(,); Hld::Dfs2(,); for(int i=;i<=m;i++)
{
k=get(); x=get(); y=get();
if(k==)
{
oper[++cnt].opt=; oper[cnt].pos=x; oper[cnt].value=a[x];
oper[++cnt].opt=; oper[cnt].pos=x; oper[cnt].value=y;
a[x]=y;
}
else
{
oper[++cnt].opt=; oper[cnt].l=x; oper[cnt].r=y; oper[cnt].k=k;
oper[cnt].cnt=++Num;
}
} Solve(,cnt,,INF); for(int i=;i<=Num;i++)
{
if(Ans[i]!=-) printf("%d",Ans[i]);
else printf("invalid request!");
printf("\n");
}
}
【BZOJ1146】【CTSC2008】网络管理 [整体二分]的更多相关文章
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- [CTSC2008]网络管理 [整体二分]
题面 bzoj luogu 所有事件按时间排序 按值划分下放 把每一个修改 改成一个删除一个插入 对于一个查询 直接查这个段区间有多少合法点 如果查询值大于等于目标值 进入左区间 如果一个查询无解 那 ...
- [BZOJ1146][CTSC2008]网络管理Network
[BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...
- 2019.01.13 bzoj1146: [CTSC2008]网络管理Network(整体二分+树剖)
传送门 题意简述:给一棵树,支持单点修改,询问路径上两点间第kkk大值. 思路: 读懂题之后立马可以想到序列上带修区间kkk大数的整体二分做法,就是用一个bitbitbit来支持查值. 那么这个题把树 ...
- BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...
- BZOJ1146——[CTSC2008]网络管理Network
1.题目大意:就是在动态的树上路径权值第k大. 2.分析:这个就是树链剖分+树套树 #include <cstdio> #include <cstdlib> #include ...
- BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...
- 【树上莫队】【带修莫队】【权值分块】bzoj1146 [CTSC2008]网络管理Network
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...
- 【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network
裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include< ...
随机推荐
- 导入execl到数据库mysql
GwykhrenyuankuList <body jwcid="$content$"> <span jwcid="@components/AppBord ...
- 在Go语言里检测内存泄漏
我们先来设定一下数据库,建立一个MySQL数据库表,名为users,里面有login_name.nickname.uid.password.forbidden几个字段,其中uid与forbidden为 ...
- android中接入twitter进行第三方登录
在应用中接入Twitter进行第三方登录时,开发人员遇到了一点问题,主要是概念有点混乱,这里把经验记录一下,帮助遇到同样问题的朋友. 一.注册应用并配置登录权限 这一步比较简单,就不多说了,直接去官网 ...
- Ubuntu16.04安装Zabbix
基于Zabbix+MySQL+Apache(可选) apt-get install php7.0-bcmath php7.0-xml php7.0-mbstring安装Zabbix所需的几个PHP模块 ...
- 当我们在安装tensorflow时,我们在安装什么?- Intro to TF, Virtualenv, Docker, CUDA, cuDNN, NCCL, Bazel
(Mainly quoted from its official website) Summary: 1. TensorFlow™ is an open source software library ...
- Halcon17无法加载"hdevenginecpp":找不到指定的模块
Halcon17无法加载"hdevenginecpp":找不到指定的模块 在C#和Halcon17混合编程中,当执行private HDevEngine MyEngine = ne ...
- java设计模式之门面模式以及在java中作用
门面模式在Tomcat中有多处使用,在Request和Response对象封装,从ApplicationContext到ServletContext封装中都用到了这种设计模式. 一个系统可以有几个门面 ...
- Python不同进制之间的转换
不同的进制 二进制 0b101 以数字0和字母b打头的表示二进制数 如果出现大于等于2的数 会抛出SyntaxError异常 八进制 0711 以数字0打头的数字表示八进制数 如果出现大于 ...
- webmagic 二次开发爬虫 爬取网站图片
webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. webmagic介绍 编写一个简单的爬虫 webmagic的使用文档:http://w ...
- C#中System.DBNull的问题
今天写一个C#的数据库Demo,第一个功能,用户登录,数据库中用户表(Staff)最后一个字段ZP(呵呵,PowerDesigner中文直接翻译的)照片字段为空, 我的登录逻辑是通过用户名以及密码查询 ...