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大的路由器的延迟时间。注意a可以等于b,此时路径上只有一个路由器。

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!

HINT

10% 测试数据满足N<=8000,Q<=3000,

40% 测试数据满足所有询问中1<=K<=5 。即路由器的延迟时间不会发生变化。

100% 测试数据满足N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N 。

绝对神题!带修改的路径上k大点权……写了我一天

其实要口头上A掉也不难……我告诉你就是把树链剖分的线段树改树套树

写的我头都大了

虽然没有道馆之战的7k代码,但是5.5k还是有的

首先把线段树换成线段树套平衡树,查找k大的时候先二分一个答案mid,然后算出从a到lca的路径上和从b到lca的路径上比mid大的点权有多少个。如果<k就更新答案,r=mid-1.否则l=mid+1

nlog^4n……我以前真的没有写过这么凶残的数据结构

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define N 80010
#define TT 3000010
#define inf 1000000000
using namespace std;
inline int read()
{
    int x=0,f=1;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;
}
//===============================================
int n,m;
int v[N];
int bin[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};
//===============================================
struct edge{int to,next;}e[2*N];
int head[N],cnt;
inline void ins(int u,int v)
{
	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
	e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
}
//===============================================
int l[TT],r[TT],rnd[TT],dat[TT],son[TT],rep[TT],root[4*N];
int treesize,wrk;
inline void update(int k){son[k]=son[l[k]]+son[r[k]]+rep[k];}
inline void tree_print(int k)
{
	if(!k)return;
	tree_print(l[k]);
	printf("%d*%d ",dat[k],rep[k]);
	tree_print(r[k]);
}
inline void right_rotate(int &k)
{
	int t=l[k];
	l[k]=r[t];
	r[t]=k;
	son[t]=son[k];
	update(k);
	k=t;
}
inline void left_rotate(int &k)
{
	int t=r[k];
	r[k]=l[t];
	l[t]=k;
	son[t]=son[k];
	update(k);
	k=t;
}
inline void insert(int &k,int x)
{
	if (!k){k=++treesize;rnd[k]=rand();dat[k]=x;rep[k]=son[k]=1;return;}
	son[k]++;
	if (x==dat[k]){rep[k]++;return;}
	else if (x<dat[k])
	{
		insert(l[k],x);
		if (rnd[l[k]]>rnd[k])right_rotate(k);
	}else if (x>dat[k])
	{
		insert(r[k],x);
		if (rnd[r[k]]>rnd[k])left_rotate(k);
	}
}
inline void del(int &k,int x)
{
	if (!k)return;
	if (x==dat[k])
	{
		if (rep[k]>1){rep[k]--;son[k]--;return;}
		if (l[k]*r[k]==0)k=l[k]+r[k];
		else if (rnd[l[k]]>rnd[r[k]]){right_rotate(k);del(k,x);}
		else {left_rotate(k);del(k,x);}
	}else if (x<dat[k])del(l[k],x),son[k]--;
	else del(r[k],x),son[k]--;
}
inline void buildtree(int k,int l,int r,int x,int d)
{
	insert(root[k],d);
	if (l==r)return;
	int mid=(l+r)>>1;
	if (x<=mid)buildtree(k<<1,l,mid,x,d);
	else buildtree(k<<1|1,mid+1,r,x,d);
}
inline void get_rank(int k,int x)
{
	if (!k)return;
	if (x==dat[k]){wrk+=son[r[k]];return;}
	if (x<dat[k])
	{
		wrk+=son[r[k]]+rep[k];
		get_rank(l[k],x);
	}else if (x>dat[k])get_rank(r[k],x);
}
inline void ask_rank(int k,int l,int r,int x,int y,int d)
{
	if (l==x&&r==y){get_rank(root[k],d);return;}
	int mid=(l+r)>>1;
	if (y<=mid)ask_rank(k<<1,l,mid,x,y,d);
	else if (x>mid)ask_rank(k<<1|1,mid+1,r,x,y,d);
	else
	{
		ask_rank(k<<1,l,mid,x,mid,d);
		ask_rank(k<<1|1,mid+1,r,mid+1,y,d);
	}
}
inline void change(int k,int l,int r,int pos,int x,int y)
{
	del(root[k],x);insert(root[k],y);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid)change(k<<1,l,mid,pos,x,y);
	else change(k<<1|1,mid+1,r,pos,x,y);
}
//===============================================
int place[4*N],pplace[4*N],belong[4*N];
int tt;
int size[N],fa[N][16],dep[N];
bool mrk[N];
inline void dfs1(int x,int d)
{
	if (mrk[x])return;mrk[x]=1;
	size[x]=1;dep[x]=d;
	for (int i=1;i<16;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
	for (int i=head[x];i;i=e[i].next)
		if (!mrk[e[i].to])
		{
			fa[e[i].to][0]=x;
			dfs1(e[i].to,d+1);
			size[x]+=size[e[i].to];
		}
}
inline void dfs2(int x,int chain)
{
	place[x]=++tt;pplace[tt]=x;belong[x]=chain;
	int mx=-1,res=-1;
	for (int i=head[x];i;i=e[i].next)
	if (e[i].to!=fa[x][0])
	{
		if (size[e[i].to]>mx)
		{
			mx=size[e[i].to];
			res=e[i].to;
		}
	}
	if (res==-1)return;
	dfs2(res,chain);
	for (int i=head[x];i;i=e[i].next)
		if (e[i].to!=res&&e[i].to!=fa[x][0])
			dfs2(e[i].to,e[i].to);
}
inline int LCA(int a,int b)
{
	if (dep[a]<dep[b])swap(a,b);
	int des=dep[a]-dep[b];
	for (int i=0;i<16;i++)
		if (des & (1<<i))a=fa[a][i];
	for (int i=15;i>=0;i--)
		if (fa[a][i]!=fa[b][i])
		{
			a=fa[a][i];
			b=fa[b][i];
		}
	if (a==b)return a;
	else return fa[a][0];
}
inline void calc(int from,int to,int d)
{
	int l,r;
	while (belong[from]!=belong[to])
	{
		l=place[belong[from]];
		r=place[from];
		ask_rank(1,1,n,l,r,d);
		from=fa[belong[from]][0];
	}
	if (place[to]+1<=place[from])
		ask_rank(1,1,n,place[to]+1,place[from],d);
}
int main()
{
	srand(1);
	n=read();m=read();
	for (int i=1;i<=n;i++)v[i]=read();
	for (int i=1;i<n;i++)
	{
		int x=read(),y=read();
		ins(x,y);
	}
	dfs1(1,0);
	dfs2(1,1);
	for (int i=1;i<=n;i++)buildtree(1,1,n,place[i],v[i]);
	for (int i=1;i<=m;i++)
	{
		int k=read(),a=read(),b=read();
		if (!k)
		{
			change(1,1,n,place[a],v[a],b);
			v[a]=b;
		}else
		{
			int lca=LCA(a,b);
			if (dep[a]+dep[b]+1-2*dep[lca]<k)
			{
				printf("invalid request!\n");
				continue;
			}
			int L=0,R=inf,ans=0;
			while (L<=R)
			{
				int md=(L+R)>>1;
				wrk=0;
				if(a!=lca)calc(a,lca,md);
				if(b!=lca)calc(b,lca,md);
				if (v[lca]>md)wrk++;
				if (wrk<k){ans=md;R=md-1;}
				else L=md+1;
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}

  

时间: 2024-10-20 09:45:41

bzoj1146 [CTSC2008]网络管理Network的相关文章

BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链上的第k大值 题解 水题. 就是烦了一点. 树链剖分+带修主席树. 带修主席树: BZOJ1901 Zju2112 Dynamic Rankings 主席树 代码 #include <cstring> #include <cstdio> #include <algorithm&g

【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network

裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 80001 #define INF 2147483647 #define NN 87001 #define BN 296 int

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

1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[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: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

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

【BZOJ 1146】 [CTSC2008]网络管理Network

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

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条高速光缆组成. 每个部门都有一个专属的路由器,

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

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

[BZOJ1146]CTSC2008网络管理|树上带修改K大

树上带修改K大,太可怕..写了树链剖分+线段树套平衡树+二分和dfs序+主席树两种,每种都是写+调试花了将近5个小时!!我实在是太弱了.. 1.   树链剖分+线段树套平衡树+二分 最显然的做法了,没啥好多说的,不过写起来真是麻烦(我太弱), 一不小心就会把线段树和平衡树的节点的域弄混,犯了超级多傻逼错误..写这题的时候还把自己树链剖分的风格改了一下,以前的实在是太麻烦了..查询的时候二分答案,统计比当前的k大的数有多少个就行了.. 2.   dfs序+主席树 考虑不带修改,那么可以对每个节点维