码迷,mamicode.com
首页 > 编程语言 > 详细

[hdu3078]Network(LCA+排序)

时间:2017-09-04 00:03:55      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:ems   stream   gre   lin   i++   pac   之间   dep   getchar   

题意:维护树上两点之间的最短路径,其一,将点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 }

 

[hdu3078]Network(LCA+排序)

标签:ems   stream   gre   lin   i++   pac   之间   dep   getchar   

原文地址:http://www.cnblogs.com/elpsycongroo/p/7471269.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!