RMQ 与 LCA-ST算法
RMQ算法
区间求最值的算法,用区间动态规划(nlogn)预处理,查询O(1)
http://blog.csdn.net/y990041769/article/details/38405063
(POJ 3264)
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<vector> #include<queue> #include<string> #include<sstream> #define eps 1e-9 #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define rep(i,j,k) for(int i=j;i<=k;i++) #define MAXN 1005 #define MAXM 40005 #define INF 0x3fffffff #define PB push_back #define MP make_pair #define X first #define Y second #define clr(x,y) memset(x,y,sizeof(x)); using namespace std; typedef long long LL; int i,j,k,n,m,x,y,T,ans,big,cas,num,len; bool flag; int a[50005],mm[50005][30],mi[50005][30]; void rmq() { for (int i=1;i<=n;i++) { mm[i][0]=mi[i][0]=a[i]; } for (int j=1;(1<<j)<=n;j++) { for (int i=1;i+(1<<j)-1<=n;i++) { mm[i][j]=max(mm[i][j-1],mm[i+(1<<(j-1))][j-1]); mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]); } } } int getans(int l,int r) { int k=0; while ((1<<(k+1))<=r-l+1) k++; int ans1=max(mm[l][k],mm[r-(1<<k)+1][k]); int ans2=min(mi[l][k],mi[r-(1<<k)+1][k]); return ans1-ans2; } int main() { while (~scanf("%d%d",&n,&m)) { clr(mm,0);clr(mi,0); for (i=1;i<=n;i++) scanf("%d",&a[i]); rmq(); for (i=1;i<=m;i++) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",getans(l,r)); } } return 0; }
大概看了看求LCA的ST算法,其思路很简单,就是树形转线性,
如果求a与b的最近公共祖先,就是确定first[a]~first[b]中深度最小的点,即求区间最小值,用RMQ维护即可。
http://blog.csdn.net/y990041769/article/details/40887469
hdu2586
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<vector> #include<queue> #include<string> #include<sstream> #define eps 1e-9 #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define rep(i,j,k) for(int i=j;i<=k;i++) #define MAXN 80005 #define MAXM 80005 #define INF 0x3fffffff #define PB push_back #define MP make_pair #define X first #define Y second #define clr(x,y) memset(x,y,sizeof(x)); using namespace std; typedef long long LL; int i,j,k,n,m,x,y,T,ans,big,cas,num,len; bool flag; int edge,head[MAXN],id[MAXN],dir[MAXN],first[MAXN],R[MAXN],vis[MAXN],tot; int dp[MAXN][25]; struct edgenode { int to,next,w; } G[MAXM]; void add_edge(int x,int y,int w) { G[edge].to=y; G[edge].w=w; G[edge].next=head[x]; head[x]=edge++; } void dfs(int u,int dep) { vis[u]=true;id[++tot]=u; first[u]=tot;R[tot]=dep; for (int i=head[u];i!=-1;i=G[i].next) { int v=G[i].to; if (!vis[v]) { int w=G[i].w; dir[v]=dir[u]+w; dfs(v,dep+1); id[++tot]=u; R[tot]=dep; } } } void ST(int n) { for (int i=1;i<=n;i++) { dp[i][0]=i; } for (int j=1;(1<<j)<=n;j++) { for (int i=1;i+(1<<j)-1<=n;i++) { int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1]; if (R[a]<R[b]) dp[i][j]=a; else dp[i][j]=b; } } } int RMQ(int l,int r) { int k=0; while ((1<<(k+1))<=r-l+1) k++; int a=dp[l][k],b=dp[r-(1<<k)+1][k]; return R[a]<R[b]?a:b; } int LCA(int u,int v) { int x=first[u],y=first[v]; if (x>y) swap(x,y); return id[RMQ(x,y)]; } int main() { scanf("%d",&T); while(T--) { memset(head,-1,sizeof(head)); edge=0;tot=0; scanf("%d%d",&n,&m); for (i=1;i<n;i++) { int x,y,d; scanf("%d%d%d",&x,&y,&d); add_edge(x,y,d); add_edge(y,x,d); } memset(vis,0,sizeof(vis)); dfs(1,1); ST(2*n-1); for (i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); int lca=LCA(u,v); printf("%d\n",dir[u]+dir[v]-2*dir[lca]); } } return 0; }