[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),輸出一行。包含一個整數為相應的延遲時間。
(全部小寫不包含引號,兩個單詞之間有一個空格)。
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大
其實先做[Cqoi2011]動態逆序對再來看這題效果更好
這題其實可以樹鏈剖分+線段樹套平衡樹+二分答案,復雜度達到了\(O(n\log^4n)\),據說能過?(反正我沒寫)
其實不要這麽麻煩,我們直接把樹剖拋棄,這樣就可以達到更加優秀的復雜度
考慮不需要修改的樹上路徑第k大,直接用主席樹,查詢4條鏈,具體題目可以見Spoj 10628. Count on a tree
直接用主席樹維護其到根的路徑上的所有點,然而添加修改操作後,每次需要將子樹內全部修改,復雜度達到了\(O(n\log n)\)
考慮我們能否不去修改子樹,那麽就可以用歐拉序來維護,在歐拉序上進行差分可以直接對子樹進行修改
所以這題的做法就很明顯了,樹狀數組套動態開點權值線段樹,樹狀數組本質上維護dfs序的位置,在其中用線段樹進行查詢
復雜度\(O(n \log^2 n)\)
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
#define lowbit(x) ((x)&(-x))
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
const int N=8e4,M=2e7;
int L[N+10],R[N+10],root[(N<<1)+10],list[(N<<1)+10],v[N+10];
int n,m,T;
struct S1{
int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
int fa[N+10],top[N+10],deep[N+10],Rem[N+10],size[N+10];
int tot,Time;
void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
void insert(int x,int y){join(x,y),join(y,x);}
void dfs(int x){
deep[x]=deep[fa[x]]+1,size[x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x]) continue;
fa[son]=x,dfs(son);
size[x]+=size[son];
if (size[Rem[x]]<size[son]) Rem[x]=son;
}
}
void build(int x){
if (!x) return;
L[x]=++Time;
top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
build(Rem[x]);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa[x]||son==Rem[x]) continue;
build(son);
}
R[x]=Time;
}
int Lca(int x,int y){
while (top[x]!=top[y]){
if (deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return deep[x]<deep[y]?x:y;
}
}HLD;//Heavy Light Decomposition
struct S2{
int ls[M+10],rs[M+10],cnt[M+10],A[50],B[50],tot;
void Modify(int &p,int l,int r,int x,int v){
if (!p) p=++tot;
cnt[p]+=v;
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) Modify(ls[p],l,mid,x,v);
else Modify(rs[p],mid+1,r,x,v);
}
void change(int i,int x,int v){for (;i<=n;i+=lowbit(i)) Modify(root[i],1,T,x,v);}
int Query(int x,int y,int w,int v,int k){
int cntA=0,cntB=0;
for (int i=x;i;i-=lowbit(i)) A[++cntA]=root[i];
for (int i=y;i;i-=lowbit(i)) A[++cntA]=root[i];
for (int i=w;i;i-=lowbit(i)) B[++cntB]=root[i];
for (int i=v;i;i-=lowbit(i)) B[++cntB]=root[i];
int l=1,r=T;
while (l!=r){
int mid=(l+r)>>1,res=0;
for (int i=1;i<=cntA;i++) res+=cnt[rs[A[i]]];
for (int i=1;i<=cntB;i++) res-=cnt[rs[B[i]]];
if (k<=res){
for (int i=1;i<=cntA;i++) A[i]=rs[A[i]];
for (int i=1;i<=cntB;i++) B[i]=rs[B[i]];
l=mid+1;
}else{
k-=res;
for (int i=1;i<=cntA;i++) A[i]=ls[A[i]];
for (int i=1;i<=cntB;i++) B[i]=ls[B[i]];
r=mid;
}
}
return l;
}
}V_ST;//Value_Segment Tree
struct S3{
int k,x,y;
S3(){k=x=y=0;}
void rd(){k=read(),x=read(),y=read();}
}Ask[N+10];
int main(){
n=read(),m=read(); int tot=0;
for (int i=1;i<=n;i++) list[++tot]=v[i]=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
HLD.insert(x,y);
}
HLD.dfs(1),HLD.build(1);
for (int i=1;i<=m;i++){
Ask[i].rd();
if (!Ask[i].k) list[++tot]=Ask[i].y;
}
sort(list+1,list+1+tot);
T=unique(list+1,list+1+tot)-list-1;
for (int i=1;i<=n;i++) v[i]=lower_bound(list+1,list+1+T,v[i])-list;
for (int i=1;i<=m;i++) if (!Ask[i].k) Ask[i].y=lower_bound(list+1,list+1+T,Ask[i].y)-list;
for (int i=1;i<=n;i++) V_ST.change(L[i],v[i],1),V_ST.change(R[i]+1,v[i],-1);
for (int i=1;i<=m;i++){
int x=Ask[i].x,y=Ask[i].y;
if (!Ask[i].k){
V_ST.change(L[x] ,v[x],-1);
V_ST.change(R[x]+1,v[x], 1);
v[x]=y;
V_ST.change(L[x] ,v[x], 1);
V_ST.change(R[x]+1,v[x],-1);
}else{
int lca=HLD.Lca(x,y),k=Ask[i].k;
int size=HLD.deep[x]+HLD.deep[y]-2*HLD.deep[lca]+1;
if (size<k){
printf("invalid request!\n");
continue;
}
printf("%d\n",list[V_ST.Query(L[x],L[y],L[lca],L[HLD.fa[lca]],k)]);
}
}
}
[CTSC2008]網絡管理Network