【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< ...
随机推荐
- Android stadio bug
好生气啊,android stadio 有bug.自己的代码,一直没有生效,原来是stadio 的问题.只是因为我打开了增强模式,后来,buildToolVersion 改了之后,android st ...
- 读取hbase数据到mysql
先写一个自己的MyRecordWriter类 extends RecordWriter package calllog; import java.io.IOException; import java ...
- laravel读excel
fileName = "test.xls";$filePath = "../storage/app/";Excel::load($filePath.$fileN ...
- iOS下原生与JS交互(总结)
iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇(我自己用的方式二,简单方便) 方式一 第一种方式是用JS ...
- Oracle11.2.0.3 RAC配置ODBC成功案例记录
最终使用字符串如下: String url="jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = scan- ...
- 《剑指offer》题解
有段时间准备找工作,囫囵吞枣地做了<剑指offer>提供的编程习题,下面是题解收集. 当初没写目录真是个坏习惯(-_-)||,自己写的东西都要到处找. 提交的源码可以在此repo中找到:h ...
- 【Swift】日期比较函数 记录下 Comparing date in Swift
Add this code to your project and comparing dates is easier than ever 扩展NSDATE //swift 3.0.2 extensi ...
- CentOS7安装Jenkins Master
一.安装java环境 1.查看服务器版本 cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 升级操作系统 yum update ...
- C++STL——set
一.相关定义 set 集合,有唯一性,即每一个元素只有一个: 是一个有序的容器,里面的元素都是排序好的: 支持插入,删除,查找等操作. 注意 set中的元素可以是任意类型的,但是由于需要排序,所以元素 ...
- CSS优化压缩
顾名思义缩写有简写意思,那就总结一下CSS缩写知识点.为什么要让CSS属性缩写?1.简化代码.一些CSS属性简写可以减少CSS代码从而减少CSS文件的占用字节.加快网页下载速度和网页加载速度.2.优化 ...