LCA notes

LCA write about issues
1.Tarjan

2.ST algorithm
first 8 column about ideas
first step: the stored data (X

//链式前向星
void add(int u,int v,int w){   
 g[cnt].v=v;    
 g[cnt].w=w;   
 g[cnt].nxt=head[u];   
 head[u]=cnt++;}

Step 2: Prepare working
depth DEP (according traversal order);
Ver traversal order;
DP-dimensional array (for storage);
First array: the first occurrence of time node;

//u为当前边 d是深度
void dfs(int u,int d){    //
cout<<ver[1]<<" dfa"<<endl;     
vis[u]=1;
//tot记录遍历顺序 初始值为0
ver[++tot]=u;   
dep[tot]=d;    
first[u]=tot;    
for(int i=head[u];i!=-1;i=g[i].nxt){        
int v=g[i].v;        
if(!vis[v]){            
dis[v]=dis[u]+g[i].w;            
dfs(v,d+1);  
//回溯??? ver数组中每个点要出现多次          
ver[++tot]=u;
dep[tot]=d; }}}

So if we ask the nearest ancestor of u and v, first find out the time interval they first appeared, and then find that in some depth interval dep, is looking lca this interval is the smallest thing

(In other words, in the process from u to v, after that a node closest to the root of the tree. After this node, we can also be back from u to v from u v, v can in order to u the shortest path dis [u] + dis [v ] -2 * dis [lca (v, u)])
to find the minimum value of the process we use to solve rmq, so more quickly
identify the most shallow depth, we return ver the beginning of the array to go, according to this number, the node identified, we are looking for lca spicy! !

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 dep[a]<dep[b]?a:b;}
//返回 dep 在 l , r 上的最小值

int LCA(int u,int v){    
int x=first[u],y=first[v];    
if(x>y)swap(x,y);    
int res=RMQ(x,y);    
return ver[res]; } 

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];            
dp[i][j]=dep[a]<dep[b]?a:b;}}}

* A stream rmq problem
rmq with most value dp thought open on one section (assumed here for the minimum, maximum empathy)
dp [i] [J] represents from position i, 2 ^ j-th power back most digital interval value on the
state transition equation

dp [i] [j] = min (dp [i] [j-1], dp [i + 2 ^ (j-1)] [j-1])
long * Poucheng from this section and other two intermediate end, each length ^ 2 (. 1-J)
1. initialization.

void ini(int n){
 for(int i=1;i<=n;i++){
  dp[i][0]=a[i];
 }
 //1<<j就是2^j了
 for(int j=0;(1<<j)<=n;j++){
  for(int i=1;i+(1<<j)-1<=n;i++){
   dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
  }
 }
}

2. Query (l, r) the value of the most

int RMQ(int l,int r){
 int k=0;
 while(1<<(k+1)<=r-l+1) k++;
 //找到最大的k,覆盖 区间
 //也可以直接k=log2(r-l+1)-1; 
 return min(dp[l][k],dp[r-(1<<k)+1][k]); 
}

A RMQ example: Cornfields
meaning of the questions is to find in a small box in seeking the maximum and minimum difference
could have been two RMQ also saw a strong memory of the search giant, I do not know will not time out?

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define N 255
using namespace std;
int dp1[N][N][8][8];
int dp2[N][N][8][8]; 
int a[N][N];
int n;
int minn(int a,int b,int c,int d){
	int m=min(a,b);
	int n=min(c,d);
	return min(m,n);
}
int maxn(int a,int b,int c,int d){
	int m=max(a,b);
	int n=max(c,d);
	return max(m,n);
}
//这里的dp[r][c][kn][km]指的是以r,c为左上角,2^kn行,2^km列的矩阵中的最值
void st(int n,int m){
	int i,j,r,c;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			dp1[i][j][0][0]=dp2[i][j][0][0]=a[i][j];
		} 
	}
	int kn=(int)(log(double(n))/log(2.0));
	int km=(int)(log(double(m))/log(2.0));
	for(i=0;i<=kn;i++){
		for(j=0;j<=km;j++){
			if(!i&&!j)continue; 
			for(r=1;r+(1<<i)-1<=n;r++){
				for(c=1;c+(1<<j)-1<=m;c++){
					if(!i){
						dp1[r][c][i][j]=min(dp1[r][c][i][j-1],dp1[r][c+(1<<(j-1))][i][j-1]);
						dp2[r][c][i][j]=max(dp2[r][c][i][j-1],dp2[r][c+(1<<(j-1))][i][j-1]);
					}
					else{
						dp1[r][c][i][j]=min(dp1[r][c][i-1][j],dp1[r+(1<<(i-1))][c][i-1][j]);
						dp2[r][c][i][j]=max(dp2[r][c][i-1][j],dp2[r+(1<<(i-1))][c][i-1][j]);
					}
				}
			}
		}
	}
 } 
int RMQ(int x,int y,int x1,int y1){
	int l=(int)(log(double(x1-x+1))/log(2.0));
	int k=(int)(log(double(y1-y+1))/log(2.0));
	return minn(dp1[x][y][l][k],dp1[x1-(1<<l)+1][y][l][k],
				dp1[x][y1-(1<<k)+1][l][k],dp1[x1-(1<<l)+1][y1-(1<<k)+1][l][k]);
	
}
int RMQ2(int x,int y,int x1,int y1){
	int l=(int)(log(double(x1-x+1))/log(2.0));
	int k=(int)(log(double(y1-y+1))/log(2.0));
	return maxn(dp2[x][y][l][k],dp2[x][y1-(1<<l)+1][l][k],
				dp2[x1-(1<<l)+1][y][l][k],dp2[x1-(1<<l)+1][y1-(1<<k)+1][l][k]);
}

int main()
{int n, b, k, i, j;
cin >> n >> b >> k;
for (i = 1; i <= n; i++)        
for (j = 1; j <= n; j++){
scanf("%d", &a[i][j]);}
st(n,n);
int u, l;    
for (i = 0; i < k; i++)
    {
scanf("%d%d", &u, &l);
    cout<<RMQ2(u,l,u+b-1,l+b-1)-RMQ(u,l,u+b-1,l+b-1)<<endl;
}
return 0;
}
法二
 int c[255][255];//记忆数组
  int max=0,min=999999999;
  if(!c[x][y]){
   for(int l=x;l<=x+b-1;l++){
   for(int c=y;c<=y+b-1;c++){
    if(a[l][c]<min) min = a[l][c];
    if(a[l][c]>max) max = a[l][c];
   } }
   c[x][y]=max-min;}
  cout<<c[x][y]<<endl;
Published 24 original articles · won praise 2 · Views 973

Guess you like

Origin blog.csdn.net/weixin_43521836/article/details/88757441
lca