zoukankan      html  css  js  c++  java
  • 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树

    【BZOJ1146】[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个,则输出信息“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序即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=80010;
    int n,m,N,nm,cnt,tot,l1,l2,l3,l4;
    int p[maxn],q[maxn],s1[maxn],s2[maxn],s3[maxn],s4[maxn],v[maxn],pa[maxn],pb[maxn],pc[maxn];
    int to[maxn<<1],next[maxn<<1],head[maxn],fa[18][maxn],dep[maxn],rt[maxn],ref[maxn<<1];
    struct number
    {
    	int val,org;
    }num[maxn<<1];
    struct node
    {
    	int siz,ls,rs;
    }s[maxn*160];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    bool cmp(number a,number b)
    {
    	return a.val<b.val;
    }
    void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void dfs(int x)
    {
    	p[x]=++q[0];
    	for(int i=head[x];i!=-1;i=next[i])
    	{
    		if(to[i]==fa[0][x])	continue;
    		fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
    	}
    	q[x]=q[0];
    }
    void insert(int &x,int l,int r,int pos,int v)
    {
    	if(!x)	x=++tot;
    	s[x].siz+=v;
    	if(l==r)	return ;
    	int mid=l+r>>1;
    	if(pos<=mid)	insert(s[x].ls,l,mid,pos,v);
    	else	insert(s[x].rs,mid+1,r,pos,v);
    }
    void updata(int x,int y,int v)
    {
    	for(int i=x;i<=n;i+=i&-i)	insert(rt[i],1,N,y,v);
    }
    int query(int l,int r,int pos)
    {
    	if(!pos)	printf("fuck
    ");
    	if(l==r)	return ref[l];
    	int sr=0,mid=l+r>>1,i;
    	for(i=1;i<=l1;i++)	sr+=s[s[s1[i]].rs].siz;
    	for(i=1;i<=l2;i++)	sr+=s[s[s2[i]].rs].siz;
    	for(i=1;i<=l3;i++)	sr-=s[s[s3[i]].rs].siz;
    	for(i=1;i<=l4;i++)	sr-=s[s[s4[i]].rs].siz;
    	if(pos<=sr)
    	{
    		for(i=1;i<=l1;i++)	s1[i]=s[s1[i]].rs;
    		for(i=1;i<=l2;i++)	s2[i]=s[s2[i]].rs;
    		for(i=1;i<=l3;i++)	s3[i]=s[s3[i]].rs;
    		for(i=1;i<=l4;i++)	s4[i]=s[s4[i]].rs;
    		return	query(mid+1,r,pos);
    	}
    	else
    	{
    		for(i=1;i<=l1;i++)	s1[i]=s[s1[i]].ls;
    		for(i=1;i<=l2;i++)	s2[i]=s[s2[i]].ls;
    		for(i=1;i<=l3;i++)	s3[i]=s[s3[i]].ls;
    		for(i=1;i<=l4;i++)	s4[i]=s[s4[i]].ls;
    		return	query(l,mid,pos-sr);
    	}
    }
    int lca(int a,int b)
    {
    	if(dep[a]<dep[b])	swap(a,b);
    	int i;
    	for(i=17;~i;i--)	if(dep[fa[i][a]]>=dep[b])	a=fa[i][a];
    	if(a==b)	return a;
    	for(i=17;~i;i--)	if(fa[i][a]!=fa[i][b])	a=fa[i][a],b=fa[i][b];
    	return fa[0][a];
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,j,a,b,c,d,e;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	num[++nm].val=rd(),num[nm].org=i;
    	for(i=1;i<n;i++)	a=rd(),b=rd(),add(a,b),add(b,a);
    	dep[1]=1,dfs(1);
    	for(j=1;(1<<j)<=n;j++)	for(i=1;i<=n;i++)	fa[j][i]=fa[j-1][fa[j-1][i]];
    	for(i=1;i<=m;i++)
    	{
    		pc[i]=rd(),pa[i]=rd(),pb[i]=rd();
    		if(!pc[i])	num[++nm].val=pb[i],num[nm].org=n+i;
    	}
    	sort(num+1,num+nm+1,cmp);
    	for(i=1;i<=nm;i++)
    	{
    		if(num[i].val>ref[N])	ref[++N]=num[i].val;
    		if(num[i].org<=n)	v[num[i].org]=N;
    		else	pb[num[i].org-n]=N;
    	}
    	for(i=1;i<=n;i++)	updata(p[i],v[i],1),updata(q[i]+1,v[i],-1);
    	for(i=1;i<=m;i++)
    	{
    		c=pc[i],a=pa[i],b=pb[i];
    		if(!c)
    		{
    			updata(p[a],v[a],-1),updata(q[a]+1,v[a],1),v[a]=b,updata(p[a],b,1),updata(q[a]+1,b,-1);
    		}
    		else
    		{
    			d=lca(a,b),e=fa[0][d],l1=l2=l3=l4=0;
    			if(dep[a]+dep[b]-dep[d]-dep[e]<c)
    			{
    				printf("invalid request!
    ");
    				continue;
    			}
    			for(j=p[a];j;j-=j&-j)	s1[++l1]=rt[j];
    			for(j=p[b];j;j-=j&-j)	s2[++l2]=rt[j];
    			for(j=p[d];j;j-=j&-j)	s3[++l3]=rt[j];
    			for(j=p[e];j;j-=j&-j)	s4[++l4]=rt[j];
    			printf("%d
    ",query(1,N,c));
    		}
    	}
    	return 0;
    }//5 5 5 1 2 3 4 3 1 2 1 4 3 5 3 1 1 1 1 1 5 2 1 5 3 1 5 2 1 2
  • 相关阅读:
    快速编辑里指定默认值
    Odoo domain 中的 like, ilike, =like, =ilike 举例说明【转】
    odoo报表条码无法显示解决[转]
    ubuntu 安装 wkhtmltopdf 的方法
    解决Odoo日期(时间)无效的问题 [转]
    ShareSDK演示
    黑客帝国数字矩阵特效做法
    lua中实现倒计时
    Lua中用Split函数分割字符串
    lua封装的位运算
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7412084.html
Copyright © 2011-2022 走看看