1. 程式人生 > >BZOJ_1146_[CTSC2008]網絡管理Network_主席樹+樹狀數組

BZOJ_1146_[CTSC2008]網絡管理Network_主席樹+樹狀數組

部門 HR inpu 局域網 一般來說 處理 root 發生 puts

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\n",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
*/

BZOJ_1146_[CTSC2008]網絡管理Network_主席樹+樹狀數組