Bzoj1146 [ctsc2008]网络管理network

Posted by yjjr's blog on December 25, 2017

标签:主席树,树状数组

题目

题目传送门

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!

分析

查询带修改的树上第K大

老套路先按dfs序建主席树,然后用树状数组维护变化量

把第K大变成第K小(和BZOJ2588类似,但是加入了修改操作)

code

我收回自己说主席树代码简单的话,这题代码量4K了,是碰到的最丧心的主席树

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<map>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read()
{
	ll f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int maxn=8100006,maxk=80006;
int cnt[maxn],ls[maxn],rs[maxn];
int root[maxk],rank[maxk<<1],tmp[maxk<<1],v[maxk<<1],a[maxk],b[maxk],c[maxk],in[maxk],out[maxk],C[maxk];
int last[maxk],deep[maxk],que[5][30],len[5],sum[5],fa[maxk][20];
struct edge{int to,next;}e[maxk<<1];
int num,tot,num1,n,m,num2,mx,cntt=0;
map<int,int> p;
inline int lowbit(int x){return x&(-x);}

void insert(int u,int v){
	e[++cntt]=(edge){v,last[u]};last[u]=cntt;
	e[++cntt]=(edge){u,last[v]};last[v]=cntt;
}

void dfs(int x){
	in[x]=++num2;
	rep(i,1,19)if((1<<i)<=deep[x])fa[x][i]=fa[fa[x][i-1]][i-1];else break;
	reg(x)
		if(e[i].to!=fa[x][0]){
			deep[e[i].to]=deep[x]+1;
			fa[e[i].to][0]=x;
			dfs(e[i].to);
		}
	out[x]=num2;
}
inline int LCA(int x,int y){
	if(deep[x]<deep[y])swap(x,y);
	int t=deep[x]-deep[y];
	rep(i,0,19)if((1<<i)&t)x=fa[x][i];
	dep(i,19,0)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
	if(x==y)return x;else return fa[x][0];
}
inline int update(int pre,int l,int r,int x,int f){
	int now=++tot,mid=(l+r)>>1;
	if(l==r){cnt[now]=cnt[pre]+f;ls[now]=rs[now]=0;}
	else{
		if(x<=mid){rs[now]=rs[pre];ls[now]=update(ls[pre],l,mid,x,f);}
		else{ls[now]=ls[pre];rs[now]=update(rs[pre],mid+1,r,x,f);}
		cnt[now]=cnt[ls[now]]+cnt[rs[now]];
	}
	return now;
}
void dfs2(int x){
	root[x]=update(root[fa[x][0]],1,mx,tmp[x],1);
	reg(x)if(e[i].to!=fa[x][0])dfs2(e[i].to);
}
inline int query(int l,int r,int rk){
	if(l==r)return l;mem(sum,0);
	rep(j,1,4)
		rep(i,1,len[j])sum[j]+=cnt[ls[que[j][i]]];
	int ans=sum[1]+sum[2]-sum[3]-sum[4],mid=(l+r)>>1;
	if(ans>=rk){
		rep(j,1,4)rep(i,1,len[j])que[j][i]=ls[que[j][i]];return query(l,mid,rk);
	}else{
		rep(j,1,4)rep(i,1,len[j])que[j][i]=rs[que[j][i]];return query(mid+1,r,rk-ans);
	}
}
int main()
{
	n=read(),m=read();num1=n;
	rep(i,1,n)v[i]=read(),tmp[i]=v[i];
	rep(i,1,n-1){int u=read(),v=read();insert(u,v);}
	rep(i,1,m){
		c[i]=read(),a[i]=read(),b[i]=read();
		if(!c[i])v[++num1]=b[i];
	}
	sort(v+1,v+1+num1);mx=1,p[v[1]]=1,rank[1]=v[1];
	rep(i,2,num1)if(v[i]!=v[i-1])rank[++mx]=v[i],p[v[i]]=mx;
	rep(i,1,n)tmp[i]=p[tmp[i]];
	dfs(1);dfs2(1);
	rep(i,1,n)C[i]=root[0];
	rep(i,1,m){
		if(c[i]){
			mem(len,0);
			int z=LCA(a[i],b[i]),num=deep[a[i]]+deep[b[i]]-2*deep[z]+1;
			que[1][++len[1]]=root[a[i]];que[2][++len[2]]=root[b[i]];que[3][++len[3]]=root[z];que[4][++len[4]]=root[fa[z][0]];
			if(num<c[i]){printf("invalid request!\n");continue;}
			for(int j=in[a[i]];j;j-=lowbit(j))que[1][++len[1]]=C[j];
			for(int j=in[b[i]];j;j-=lowbit(j))que[2][++len[2]]=C[j];
			for(int j=in[z];j;j-=lowbit(j))que[3][++len[3]]=C[j];
			for(int j=in[fa[z][0]];j;j-=lowbit(j))que[4][++len[4]]=C[j];
			printf("%d\n",rank[query(1,mx,num-c[i]+1)]);
		}else{
			for(int j=in[a[i]];j<=n;j+=lowbit(j))C[j]=update(C[j],1,mx,tmp[a[i]],-1);
			for(int j=out[a[i]]+1;j<=n;j+=lowbit(j))C[j]=update(C[j],1,mx,tmp[a[i]],1);
			tmp[a[i]]=p[b[i]];
			for(int j=in[a[i]];j<=n;j+=lowbit(j))C[j]=update(C[j],1,mx,tmp[a[i]],1);
			for(int j=out[a[i]]+1;j<=n;j+=lowbit(j))C[j]=update(C[j],1,mx,tmp[a[i]],-1);
		}
	}
	return 0;
}
本文可以转载,但必须附上原文链接,否则你会终生找不到妹子!!!欢迎关注我的CSDN: ahyjjr