1146: [CTSC2008]网络管理Network

Time Limit: 50 Sec  Memory Limit: 162 MB
Submit: 3522  Solved: 1041
[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大的路由器的延迟时间。注意N
,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N

Output

  对于每一个第二种询问(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!

把前两道主席树的题融合起来..........
问题在于,树状数组来维护的必须用dfs序,然后我才发现我dfs序多么不清,想了好长时间才明白,什么时候总结一下dfs序
节点x修改,询问一段路径l->r
节点x修改只对子树中与外界交流有影响,而子树在dfs序中是一段区间[L[x],R[x]],对这一段用差分的修改方法就行了
lca用树剖求的
有个地方忘Bin竟然还有50分
//
// main.cpp
// bzoj1146
//
// Created by Candy on 2016/12/31.
// Copyright ? 2016年 Candy. All rights reserved.
// #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc(x) t[x].l
#define rc(x) t[x].r
typedef long long ll;
const int N=8e4+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,w[N],u,v,k;
int mp[N<<],m;
struct ques{
int k,a,b;
}q[N];
void getMP(){
sort(mp+,mp++m);
int p=;mp[++p]=mp[];
for(int i=;i<=m;i++) if(mp[i]!=mp[i-]) mp[++p]=mp[i];
m=p;
}
int Bin(int v){
int l=,r=m;
while(l<=r){
int mid=(l+r)>>;
if(mp[mid]==v) return mid;
else if(v<mp[mid]) r=mid-;
else l=mid+;
}
return ;
} struct edge{
int v,ne;
}e[N<<];
int h[N],cnt;
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int deep[N],fa[N],mx[N],size[N],top[N],tid[N],tot;
int L[N],R[N];
void dfs(int u){
size[u]=;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u;deep[v]=deep[u]+;
dfs(v);
size[u]+=size[v];
if(size[v]>size[mx[u]]) mx[u]=v;
}
}
void dfs(int u,int anc){
if(!u) return;
tid[u]=L[u]=++tot;
top[u]=anc;
dfs(mx[u],anc);
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa[u]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v);
R[u]=tot;
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(tid[x]>tid[y]) swap(x,y);
return x;
} struct node{
int l,r,w;
}t[N*];
int crt[N],rt[N],sz;
void ins(int &x,int l,int r,int p,int d){//printf("ins %d %d %d %d %d\n",x,l,r,p,d);
t[++sz]=t[x];x=sz;
t[x].w+=d;
if(l==r) return;
int mid=(l+r)>>;
if(p<=mid) ins(lc(x),l,mid,p,d);
else ins(rc(x),mid+,r,p,d);
}
void build(int u){//printf("build %d\n",u);
if(!u) return;
rt[u]=rt[fa[u]];
ins(rt[u],,m,w[u],);
build(mx[u]);
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa[u]&&e[i].v!=mx[u]) build(e[i].v);
} inline int lowbit(int x){return x&-x;}
void add(int x,int v,int d){
for(int i=x;i<=tot;i+=lowbit(i)) ins(crt[i],,m,v,d);
}
int A[N<<],B[N<<],a,b;
bool check(int k){
int suml=,sumr=;
for(int i=;i<=a;i++) suml+=t[A[i]].w;
for(int i=;i<=b;i++) sumr+=t[B[i]].w;
//printf("check %d %d\n",sumr,suml);
return sumr-suml>=k;
}
int cal(){
int suml=,sumr=;
for(int i=;i<=a;i++) suml+=t[rc(A[i])].w;
for(int i=;i<=b;i++) sumr+=t[rc(B[i])].w;
//printf("cal %d %d\n",sumr,suml);
return sumr-suml;
}
void query(int ql,int qr,int k){
a=b=;int p=lca(ql,qr);//printf("que %d %d %d %d %d\n",ql,qr,k,p,fa[p]);
B[++b]=rt[ql];B[++b]=rt[qr];
A[++a]=rt[p];A[++a]=rt[fa[p]];
for(int i=L[ql];i;i-=lowbit(i)) B[++b]=crt[i];
for(int i=L[qr];i;i-=lowbit(i)) B[++b]=crt[i];
for(int i=L[p];i;i-=lowbit(i)) A[++a]=crt[i];
for(int i=L[fa[p]];i;i-=lowbit(i)) A[++a]=crt[i];
if(!check(k)){puts("invalid request!");return;}
int l=,r=m;
while(l<r){
int mid=(l+r)>>,rsize=cal();//printf("erfen %d %d %d %d\n",l,r,mid,rsize);
if(rsize>=k){
l=mid+;
for(int i=;i<=a;i++) A[i]=rc(A[i]);
for(int i=;i<=b;i++) B[i]=rc(B[i]);
}else{
r=mid;
k-=rsize;
for(int i=;i<=a;i++) A[i]=lc(A[i]);
for(int i=;i<=b;i++) B[i]=lc(B[i]);
}
}
printf("%d\n",mp[l]);
}
void solve(){
build();
for(int i=;i<=Q;i++){
int k=q[i].k,a=q[i].a,b=q[i].b;
if(k==){
add(L[a],w[a],-);add(R[a]+,w[a],);
w[a]=Bin(b);
add(L[a],w[a],);add(R[a]+,w[a],-);
}else{
query(a,b,k);
}
}
}
void tet(){
for(int i=;i<=n;i++)
printf("dfs %d %d\n",L[i],R[i]);
}
int main(int argc, const char * argv[]) {
n=read();Q=read();
for(int i=;i<=n;i++) mp[++m]=w[i]=read();
for(int i=;i<=n-;i++) u=read(),v=read(),ins(u,v);
dfs();dfs(,);//tet();
for(int i=;i<=Q;i++){
q[i].k=read(),q[i].a=read(),q[i].b=read();
if(q[i].k==) mp[++m]=q[i].b;
}
getMP();
for(int i=;i<=n;i++) w[i]=Bin(w[i]);
solve();
return ;
}
 

BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]的更多相关文章

  1. BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序

    Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路 ...

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

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

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

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

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

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  5. bzoj 1146 [CTSC2008]网络管理Network

    很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...

  6. BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树

    题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...

  7. [BZOJ3295] [Cqoi2011]动态逆序对(带修改主席树)

    题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...

  8. 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

    少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...

  9. 【bzoj1901】dynamic ranking(带修改主席树/树套树)

    题面地址(权限题) 不用权限题的地址 首先说说怎么搞带修改主席树? 回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth. 那么我们如何支持修改操作 ...

随机推荐

  1. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  2. PHP源码分析-变量

    1. 变量的三要素变量名称,变量类型,变量值 那么在PHP用户态下变量类型都有哪些,如下: // Zend/zend.h #define IS_NULL 0 #define IS_LONG 1 #de ...

  3. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  4. css常用hack

    原文地址:css常用hack 突然想起今天早上在CNZZ看到的统计数据,使用IE6.7的用户比例还真多,看到之后我的心都碎了.微软都放弃了为毛还有这么多人不死心? 所以说,IE下的兼容还是得做的. – ...

  5. 开发者的利器:Docker 理解与使用

    困扰写代码的机器难免会被我们安装上各种各样的开发工具.语言运行环境和引用库等一大堆的东西,长久以来不仅机器乱七八糟,而且有些相同的软件还有可能会安装不同的版本,这样又会导致一个项目正常运行了,却不小心 ...

  6. JQuery的基础和应用

    <参考文档>   1.什么是?    DOM的作用:提供了一种动态的操作HTML元素的方法.    jQuery是一个优秀的js库.用来操作HTML元素的工具.    jQuery和DOM ...

  7. iOS在导航栏上居中显示分段控件(UISegmentedControl)

    UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:nil]; segmentedCont ...

  8. atitit.细节决定成败的适合情形与缺点

    atitit.细节决定成败的适合情形与缺点 1. 在理论界有两种观点:一种是"细节决定成败",另一种是"战略决定成败".1 1.1. 格局决定成败,方向决定成败 ...

  9. T-SQL 拆分使用指定分隔符的字符串(split string)

    比如有一个表,我们需要些一个语句像SELECT OtherID, SplitData WHERE SomeID = 'abcdef-.......' , 然后就能返回分割成单独的行. 原表: | So ...

  10. Firefox开发者专版浏览器,Web开发者利器.

    2015的11月9日,Firefox迎来了自己的十周岁生日.在庆祝Firefox十周年之际,Mozilla发布了Firefox开发者专版,这是首款专门为开发者打造的浏览器. 浏览器中独特的暗色调设计. ...