[BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)
题目描述
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。
【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:
-
由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。
-
查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
输入输出格式
输入格式:
第一行为两个整数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,此时路径上只有一个路由器。
输出格式:
对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足k个,则输出信息“invalid request!”(全部小写不包含引号,两个单词之间有一个空格)。
输入输出样例
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
3 2 2 invalid request!
说明
测试数据满足N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N 。
题解
带修树链第k大
据说能用树剖+线段树套平衡树4个log稳过?
据说能用树剖+树状数组套主席树3个log?
据说能把树剖去了两个log?
据说还能一个log?
蒟蒻表示很懵逼……只会用树状数组套主席树的……
首先这是一棵树,要在树上跑主席树两种方法,一种是每一次在父亲的树的基础上加值,然而那样就不资瓷修改了(大概?蒟蒻也不是很清楚)
或者用括号序列的思想,每一个点dfs进的时候存个点,出去的时候存个点,这样就可以用差分来跑主席树了(具体细节看代码)
然后是修改……我就当你们都会待修改主席树了(不懂的可以去看看这道题->动态逆序对)
然后……大概就这样?
时间复杂度应该是两个log吧(树剖用来求LCA的应该不算在里面)
ps:调主席树update的时候写成$ch[x][0]$和$ch[x][1]$了……调了半天啥错都找不到orz
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 inline int read(){ 9 #define num ch-'0' 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch=='-')&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 const int N=80005; 19 struct node{ 20 int op,x,y; 21 }Q[N]; 22 int n,m,q,b[N<<1],lim; 23 int rt[N<<1],L[N<<8],R[N<<8],sz[N<<8],cnt; 24 void update(int &p,int l,int r,int pos,int val){ 25 if(!p) p=++cnt;sz[p]+=val; 26 if(l==r) return; 27 int mid=l+r>>1; 28 if(pos<=mid) update(L[p],l,mid,pos,val); 29 else update(R[p],mid+1,r,pos,val); 30 } 31 void update(int x,int val,int op){ 32 for(;x<=m;x+=x&-x) update(rt[x],1,lim,val,op); 33 } 34 int ver[N<<1],Next[N<<1],head[N],tot; 35 int fa[N],dep[N],top[N],size[N],son[N],ls[N],rs[N],sum[N],val[N],num; 36 inline void add(int u,int v){ 37 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 38 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 39 } 40 void dfs1(int u){ 41 size[u]=1,dep[u]=dep[fa[u]]+1; 42 for(int i=head[u];i;i=Next[i]){ 43 int v=ver[i]; 44 if(v!=fa[u]){ 45 fa[v]=u,dfs1(v),size[u]+=size[v]; 46 if(size[v]>size[son[u]]) son[u]=v; 47 } 48 } 49 } 50 void dfs2(int u,int t){ 51 top[u]=t,ls[u]=++num; 52 update(ls[u],val[u],1); 53 if(son[u]){ 54 dfs2(son[u],t); 55 for(int i=head[u];i;i=Next[i]){ 56 int v=ver[i]; 57 if(v!=fa[u]&&v!=son[u]) dfs2(v,v); 58 } 59 } 60 rs[u]=++num; 61 update(rs[u]+1,val[u],-1); 62 } 63 int LCA(int u,int v){ 64 while(top[u]!=top[v]){ 65 if(dep[top[u]]<dep[top[v]]) swap(u,v); 66 u=fa[top[u]]; 67 } 68 return dep[u]<dep[v]?u:v; 69 } 70 int sta[1005],stb[1005],cnta,cntb; 71 inline void get(int x,int op){ 72 if(~op){ 73 for(;x;x-=x&-x) sta[++cnta]=rt[x]; 74 } 75 else{ 76 for(;x;x-=x&-x) stb[++cntb]=rt[x]; 77 } 78 } 79 int query(int l,int r,int k){ 80 if(l==r) return b[l]; 81 int mid=l+r>>1,sum=0; 82 for(int i=1;i<=cnta;++i) sum+=sz[R[sta[i]]]; 83 for(int i=1;i<=cntb;++i) sum-=sz[R[stb[i]]]; 84 if(sum>=k){ 85 for(int i=1;i<=cnta;++i) sta[i]=R[sta[i]]; 86 for(int i=1;i<=cntb;++i) stb[i]=R[stb[i]]; 87 return query(mid+1,r,k); 88 } 89 else{ 90 for(int i=1;i<=cnta;++i) sta[i]=L[sta[i]]; 91 for(int i=1;i<=cntb;++i) stb[i]=L[stb[i]]; 92 return query(l,mid,k-sum); 93 } 94 } 95 inline void getans(int u,int v,int k){ 96 int lca=LCA(u,v); 97 if(k>dep[u]+dep[v]-(dep[lca]<<1)+1) return (void)(puts("invalid request!")); 98 cnta=cntb=0; 99 get(ls[u],1),get(ls[lca],-1); 100 get(ls[v],1),get(ls[fa[lca]],-1); 101 printf("%d\n",query(1,lim,k)); 102 } 103 inline void change(int pos,int v){ 104 update(ls[pos],val[pos],-1),update(rs[pos]+1,val[pos],1),val[pos]=v; 105 update(ls[pos],v,1),update(rs[pos]+1,v,-1); 106 } 107 int main(){ 108 //freopen("testdata.in","r",stdin); 109 n=read(),q=read(),m=n<<1; 110 for(int i=1;i<=n;++i) b[++lim]=val[i]=read(); 111 for(int i=1;i<n;++i){ 112 int u=read(),v=read();add(u,v); 113 } 114 for(int i=1;i<=q;++i){ 115 int op=read(),x=read(),y=read(); 116 Q[i]=(node){op,x,y}; 117 if(!op) b[++lim]=y; 118 } 119 sort(b+1,b+1+lim),lim=unique(b+1,b+1+lim)-b-1; 120 for(int i=1;i<=n;++i) val[i]=lower_bound(b+1,b+1+lim,val[i])-b; 121 dfs1(1),dfs2(1,1); 122 for(int i=1;i<=q;++i){ 123 int op=Q[i].op,x=Q[i].x,y=Q[i].y; 124 if(op) getans(x,y,op); 125 else y=lower_bound(b+1,b+1+lim,y)-b,change(x,y); 126 } 127 return 0; 128 }