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

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+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,Q,w[N],u,v,k;
int mp[N<<1],m;
struct ques{
    int k,a,b;
}q[N];
void getMP(){
    sort(mp+1,mp+1+m);
    int p=0;mp[++p]=mp[1];
    for(int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
    m=p;
}
int Bin(int v){
    int l=1,r=m;
    while(l<=r){
        int mid=(l+r)>>1;
        if(mp[mid]==v) return mid;
        else if(v<mp[mid]) r=mid-1;
        else l=mid+1;
    }
    return 0;
}

struct edge{
    int v,ne;
}e[N<<1];
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]=1;
    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]+1;
        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*128];
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)>>1;
    if(p<=mid) ins(lc(x),l,mid,p,d);
    else ins(rc(x),mid+1,r,p,d);
}
void build(int u){//printf("build %d\n",u);
    if(!u) return;
    rt[u]=rt[fa[u]];
    ins(rt[u],1,m,w[u],1);
    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],1,m,v,d);
}
int A[N<<1],B[N<<1],a,b;
bool check(int k){
    int suml=0,sumr=0;
    for(int i=1;i<=a;i++) suml+=t[A[i]].w;
    for(int i=1;i<=b;i++) sumr+=t[B[i]].w;
    //printf("check %d %d\n",sumr,suml);
    return sumr-suml>=k;
}
int cal(){
    int suml=0,sumr=0;
    for(int i=1;i<=a;i++) suml+=t[rc(A[i])].w;
    for(int i=1;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=0;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=1,r=m;
    while(l<r){
        int mid=(l+r)>>1,rsize=cal();//printf("erfen %d %d %d %d\n",l,r,mid,rsize);
        if(rsize>=k){
            l=mid+1;
            for(int i=1;i<=a;i++) A[i]=rc(A[i]);
            for(int i=1;i<=b;i++) B[i]=rc(B[i]);
        }else{
            r=mid;
            k-=rsize;
            for(int i=1;i<=a;i++) A[i]=lc(A[i]);
            for(int i=1;i<=b;i++) B[i]=lc(B[i]);
        }
    }
    printf("%d\n",mp[l]);
}
void solve(){
    build(1);
    for(int i=1;i<=Q;i++){
        int k=q[i].k,a=q[i].a,b=q[i].b;
        if(k==0){
            add(L[a],w[a],-1);add(R[a]+1,w[a],1);
            w[a]=Bin(b);
            add(L[a],w[a],1);add(R[a]+1,w[a],-1);
        }else{
            query(a,b,k);
        }
    }
}
void tet(){
    for(int i=1;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=1;i<=n;i++) mp[++m]=w[i]=read();
    for(int i=1;i<=n-1;i++) u=read(),v=read(),ins(u,v);
    dfs(1);dfs(1,1);//tet();
    for(int i=1;i<=Q;i++){
        q[i].k=read(),q[i].a=read(),q[i].b=read();
        if(q[i].k==0) mp[++m]=q[i].b;
    }
    getMP();
    for(int i=1;i<=n;i++) w[i]=Bin(w[i]);
    solve();
    return 0;
}
时间: 2024-08-09 07:56:43

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

BZOJ 1146: [CTSC2008]网络管理Network

1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3539  Solved: 1054[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成. 每个部门都有一个专属的路由器,

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

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

[BZOJ 1146]网络管理Network 树上带修改路径k值

题目意思非常清楚,就是要求树上带修改的路径k大值 如果不带修改的话,我会用树上主席树去搞,以父子关系建树,可以参见 [BZOJ 3123]森林 但是带修改就不会打了QAQ,于是去学了另一种在dfs序上搞的方法(同时感谢呵呵酵母菌的帮助) 其实思想是一样的,就是搞出来节点到根路径的线段树,然后用x+y-lca-fa(lca)去差分出来树上路径的线段树,再去里面查询k值 那么我们怎么得到点到根路径的线段树呢?可以在dfs序上差分啊! dfs序列上的dfnl[x]~dfnr[x]包含的是以x为根节点的

BZOJ 1901 Zju 2112 Dynamic Rankings 带修改主席树

题目大意:给出一个序列,单点修改,询问区间第k大. 思路:如果不带修改,那么划分树就可以解决,但是划分树是静态的树,不支持修改.带修改的主席舒其实就是外层fenwick套内层权值线段树,但是权值线段树必须动态开节点.然后修改的时候就像树状数组修改那样,每次修改logn个权值线段树.查询的时候也一样,返回logn个权值线段树统计的和. 最后为了求区间第k大,还需要二分答案. CODE: #include <cstdio> #include <cstring> #include <

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要

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

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写,不会的同学可以看一下这个. 加上修改怎么做呢?我们可以用数学老师成天讲的类比思想: 可以发现,不修改的区间k小问题中,每加入一个原序列中的数,对应的主席树在上一个的基础上进行修改,而查询的时候用右端点主席树减去左端点左边的主席树.这样的操作就像是维护前缀和:每次加入一个元素的时候,sum[i] =

【BZOJ 1146】网络管理Network

Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些

【模板】 带修改主席树

也就是树状数组加线段树 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=5e4+7; 4 struct node{ 5 int l,r,sum; 6 }tr[N<<3]; 7 struct quer{ 8 int l,r,k,v,op; 9 }q[10000+7]; 10 int rtn,Ln,Rn; 11 int a[N],b[N],rt[N<<2],L[N<<2],R[N<