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; }