zoukankan      html  css  js  c++  java
  • BZOJ_1146_[CTSC2008]网络管理Network_主席树+树状数组

    BZOJ_1146_[CTSC2008]网络管理Network_主席树

    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个,则输出信息“invalidrequest!”
    (全部小写不包含引号,两个单词之间有一个空格)。

    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!

     一般来说主席树维护树上信息的时候都是每个点维护点到根路径上的信息。
    但这样还是在树上,修改不是很方便,于是把它放到序列上。
    建立出栈入栈序,每个点在入栈的地方+1,出栈的位置-1。
    前缀和就是这个点到根路径上的信息,转化成了序列问题。
    然后这些操作都用树状数组做一下即可。
    我这里写的有隐患,不能认为子树中最后出现的结点+1就是出栈的位置。
    因为如果维护一些别的信息时,需要修改那个结点的信息,这样前一个点的出栈位置维护的信息就会也被修改。
    并且空间也要开两倍。
     
    (第k大)
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 80050
    #define maxn 100000000
    int n,m,head[N],to[N<<1],nxt[N<<1],val[N],dfn[N],cnt,out[N];
    int fa[N],top[N],son[N],size[N],dep[N],tot,A[N],B[N],C[N],D[N];
    int siz[N*250],ls[N*250],rs[N*250],root[N];
    inline void add(int u,int v) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    void insert(int &y,int l,int r,int v,int c) {
    	if(!y) y=++tot; siz[y]+=c;
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	if(v<=mid) insert(ls[y],l,mid,v,c);
    	else insert(rs[y],mid+1,r,v,c);
    }
    void dfs1(int x,int y) {
    	int i; dep[x]=dep[y]+1; fa[x]=y; size[x]=1; dfn[x]=++dfn[0];
    	for(i=dfn[x];i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],1);
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		dfs1(to[i],x); size[x]+=size[to[i]]; if(size[to[i]]>size[son[x]]) son[x]=to[i];
    	}
    	for(i=dfn[0]+1;i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],-1);
    	out[x]=dfn[0]+1;
    }
    void dfs2(int x,int t) {
    	top[x]=t; if(son[x]) dfs2(son[x],t); int i;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
    }
    int lca(int x,int y) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]>dep[top[y]]) swap(x,y);
    		y=fa[top[y]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    int query(int l,int r,int k) {
    	if(l==r) return l;
    	int mid=(l+r)>>1,i,sizls=0;
    	for(i=1;i<=A[0];i++) sizls+=siz[ls[A[i]]];
    	for(i=1;i<=B[0];i++) sizls+=siz[ls[B[i]]];
    	for(i=1;i<=C[0];i++) sizls-=siz[ls[C[i]]];
    	for(i=1;i<=D[0];i++) sizls-=siz[ls[D[i]]];
    	if(k<=sizls) {
    		for(i=1;i<=A[0];i++) A[i]=ls[A[i]];
    		for(i=1;i<=B[0];i++) B[i]=ls[B[i]];
    		for(i=1;i<=C[0];i++) C[i]=ls[C[i]];
    		for(i=1;i<=D[0];i++) D[i]=ls[D[i]];
    		return query(l,mid,k);
    	}else {
    		for(i=1;i<=A[0];i++) A[i]=rs[A[i]];
    		for(i=1;i<=B[0];i++) B[i]=rs[B[i]];
    		for(i=1;i<=C[0];i++) C[i]=rs[C[i]];
    		for(i=1;i<=D[0];i++) D[i]=rs[D[i]];
    		return query(mid+1,r,k-sizls);
    	}
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	int i,x,y,k;
    	for(i=1;i<=n;i++) scanf("%d",&val[i]);
    	for(i=1;i<n;i++) {
    		scanf("%d%d",&x,&y); add(x,y); add(y,x);
    	}
    	dfs1(1,0); dfs2(1,1);
    	while(m--) {
    		scanf("%d%d%d",&k,&x,&y);
    		if(!k) {
    			for(i=dfn[x];i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],-1);
    			for(i=out[x];i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],1);
    			val[x]=y;
    			for(i=dfn[x];i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],1);
    			for(i=out[x];i<=n;i+=i&(-i)) insert(root[i],0,maxn,val[x],-1);
    		}else {
    			A[0]=B[0]=C[0]=D[0]=0;
    			int l=lca(x,y),len=dep[x]+dep[y]-dep[l]-dep[fa[l]];
    			if(len<k) puts("invalid request!");
    			else {
    				k=len-k+1;
    				for(i=dfn[x];i;i-=i&(-i)) A[++A[0]]=root[i];
    				for(i=dfn[y];i;i-=i&(-i)) B[++B[0]]=root[i];
    				for(i=dfn[l];i;i-=i&(-i)) C[++C[0]]=root[i];
    				if(fa[l]) for(i=dfn[fa[l]];i;i-=i&(-i)) D[++D[0]]=root[i];
    				printf("%d
    ",query(0,maxn,k));
    			}
    		}
    	}
    }
    /*
    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
    */
    
  • 相关阅读:
    Java转大数据开发全套视频资料
    Java注解Annotation的用法
    SpringBoot集成CAS单点登录,SSO单点登录,CAS单点登录(视频资料分享篇)
    零基础如何学习Java和web前端
    如何看待B站疑似源码泄漏的问题?
    如何自学编程,零基础适合学习Java或者Web前端吗,非科班的能学java吗?
    Spring中常用的注解,你知道几个呢?
    学习分布式系统需要怎样的知识?
    程序员如何学习互联网前言技术呢,我给你10个建议
    回看面试中的这些坑,你踩过几个?
  • 原文地址:https://www.cnblogs.com/suika/p/8967719.html
Copyright © 2011-2022 走看看