[hdu3078]Network(LCA+排序)
题意:维护树上两点之间的最短路径,其一,将点a的值变为b,其二,求路径上第k大的值。
解题关键:LCA+sort
复杂度:$O(qn\log n + n\log n)$ 数据弱不怪我
1 //#pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cmath> 7 #include<iostream> 8 #include<vector> 9 typedef long long ll; 10 using namespace std; 11 const int maxn=81000; 12 const int maxm=30; 13 int _pow[maxm],m,n; 14 int head[maxn],tot; 15 int ver[maxn*2],depth[maxn*2],first[maxn],rmq[maxn*2][25],id;//5个数组,注意哪个需要乘2 16 int pre[maxn],val[maxn]; 17 inline int read(){ 18 char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar()); 19 int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0'; 20 if(k=='-')x=0-x;return x; 21 } 22 23 struct edge{ 24 int to,nxt; 25 }e[maxn*2];//链式前向星建树 26 27 void init(){ 28 memset(head,-1,sizeof head); 29 tot=0; 30 id=0; 31 } 32 33 void add_edge(int u,int v){ 34 e[tot].to=v; 35 e[tot].nxt=head[u]; 36 head[u]=tot++; 37 } 38 39 void dfs(int u,int fa,int dep){ 40 ver[++id]=u;//第i个访问到的结点编号 41 depth[id]=dep;//第i个访问到的结点深度 42 first[u]=id; 43 for(int i=head[u];i!=-1;i=e[i].nxt){ 44 int v=e[i].to; 45 if(v==fa) continue; 46 pre[v]=u; 47 dfs(v,u,dep+1); 48 ver[++id]=u;//后序遍历,再次访问父节点 49 depth[id]=dep; 50 } 51 } 52 53 void rmq_init(int n){ 54 int k=int(log(n)/log(2)); 55 for(int i=1;i<=n;++i) rmq[i][0]=i; 56 for(int j=1;j<=k;++j){ 57 for(int i=1;i+_pow[j]-1<=n;++i){//因为存的是索引 58 int a=rmq[i][j-1],b=rmq[i+_pow[j-1]][j-1]; 59 rmq[i][j]=depth[a]<depth[b]?a:b; 60 } 61 } 62 } 63 64 int rmq_query(int l,int r){ 65 int k=int(log(r-l+1.0)/log(2.0)); 66 int a=rmq[l][k],b=rmq[r-_pow[k]+1][k]; 67 return depth[a]<depth[b]?a:b; 68 }//返回的依然是索引 69 70 int LCA(int u,int v){ 71 int x=first[u],y=first[v]; 72 if(x>y)swap(x,y); 73 int res=rmq_query(x,y); 74 return ver[res]; 75 } 76 77 vector<int>path; 78 //int path[maxn]; 79 void solve(int k,int a,int b){ 80 //int cnt=0; 81 path.clear(); 82 int lca=LCA(a,b); 83 while(b!=lca) path.push_back(val[b]),b=pre[b]; 84 while(a!=lca) path.push_back(val[a]),a=pre[a]; 85 path.push_back(val[lca]); 86 if(path.size()<k){ 87 printf("invalid request!\n"); 88 return; 89 } 90 sort(path.begin(),path.end(),greater<int>()); 91 printf("%d\n",path[k-1]); 92 return; 93 } 94 95 int main(){ 96 for(int i=0;i<maxm;++i) _pow[i]=1<<i; //预处理2^n 97 int k,a,b; 98 n=read();m=read(); 99 init(); 100 for(int i=1;i<=n;i++) val[i]=read(); 101 for(int i=0;i<n-1;++i){ 102 a=read(),b=read(); 103 add_edge(a,b); 104 add_edge(b,a); 105 } 106 dfs(1,-1,0); 107 rmq_init(2*n-1); 108 for(int i=0;i<m;++i){ 109 k=read();a=read();b=read(); 110 if(k) solve(k,a,b); 111 else val[a]=b; 112 } 113 114 return 0; 115 }