装逼的英语解释了好多意义:

RMQ是基础:Range Max/Min Query:查找区间的最大或者最小的算法:见刘汝佳训练指南P197-P198

思想:dp【i】【j】表示从i开始的,长度为2^j的一段元素的最小值

点我就搞懂了RMQ


例题:网络赛签到题:HDOJ5443TheWaterProblem


LCA:lowest common ancestor:最近公共祖先

http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html

http://ayzk.wordpress.com.cn/archives/14


例题:

POJ 1330 bin神模板过之

HDOJ 2586

变化:题中树上边有权值

代码改动:

《1》再定义一个数组,dir【】表示该点离根的距离

《2》addedge在加边时需要多添加一个参数:两点距离

《3》lca求出来的是位置坐标

《4》在dfs中需要记录节点离根的距离即:dir【v】=dir【u】+edge【】。cost

《5》最后答案ans=dir【u】+dir【v】-dir【lca】:自己画图就明白了的


倍增法:二进制压缩思路:http://blog.csdn.net/lanshui_yang/article/details/11746513

模板就是这么666


贴上我bin的模板:可以裸过POJ 1330

int rmq[2*maxn];
struct ST{
	int mm[2*maxn];
	int dp[2*maxn][20];
	void init(int n){
		mm[0]=-1;
		for(int i=1;i<=n;i++){
			mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
			dp[i][0]=i;
		}
		for(int j=1;j<=mm[n];j++)
			for(int i=1;i+(1<<j)-1<=n;i++) 
				dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
	}
	int query(int a,int b){
		if (a>b) swap(a,b);
		int k=mm[b-a+1];
		return rmq[dp[a][k]]<=rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
	}
};

struct Edge{
	int to,Next;
}edge[maxn*2];

int tot,head[maxn];
int F[maxn*2];
int P[maxn];
int cnt;
ST st;

void init(){
	tot=0;
	memset(head,-1,sizeof(head));
}

void addedge(int u,int v){
	edge[tot].to=v;
	edge[tot].Next=head[u];
	head[u]=tot++;
}

void dfs(int u,int pre,int dep){
	F[++cnt]=u;
	rmq[cnt]=dep;
	P[u]=cnt;
	for(int i=head[u];i!=-1;i=edge[i].Next){
		int v=edge[i].to;
		if (v==pre) continue;
		dfs(v,u,dep+1);
		F[++cnt]=u;
		rmq[cnt]=dep;
	}
}

void LCA_init(int root,int node_num){
	cnt=0;
	dfs(root,root,0);
	st.init(2*node_num-1);
}

int query_lca(int u,int v){
	return F[st.query(P[u],P[v])];
}

bool flag[maxn];

int main(){
	//input;
	int T,N,u,v;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&N);
		init();
		memset(flag,false,sizeof(flag));
		for(int i=1;i<N;i++){
			scanf("%d%d",&u,&v);
			addedge(u,v);
			addedge(v,u);
			flag[v]=true;
		}
		int root;
		for(int i=1;i<=N;i++)
			if (!flag[i]){
				root=i;
				break;
			}
		LCA_init(root,N);
		scanf("%d%d",&u,&v);
		printf("%d\n",query_lca(u,v));
	}
	return 0;
}