hdu5726

题意:给定一个序列,多次询问[L,R],输出这段区间的最大公约数,以及为此公约数的区间个数。

思路,用RMQ处理,然后对每个左端点i,二分搜索最远的右端点R,使i到这个端点区间内最大公约数相同,用MAP记录此段区间个数,一直处理到R=n;

二分搜索不知为什么用while(high-low>1)这种总是WA,自己写的样例却都对。。保险起见,以后还是用while(low<=high)这种吧

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

int a[100000+5];
int dp[100000+5][30];
int n;
map MAP_cnt;

int gcd(int x,int y){
	if(y==0){
		return x;
	}else
	    return gcd(y,x%y);
}

void init(){
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		dp[i][0]=a[i];
	}
	for(int j=1;(1<>T;
	for(int CASE=1;CASE<=T;CASE++){
		MAP_cnt.clear();
		scanf("%d",&n);
		init();
		for(int i=1;i<=n;i++){
			int L=i,R=i;
			while(R<=n){
				int low=L,high=n;
				int t=RMQ(i,L);
				while(low<=high){
					int mid=(high+low)/2;
					if(RMQ(i,mid)==t){
						low=mid+1;
					}else{
						high=mid-1;
					}	
				}
				R=low;
				MAP_cnt[t]+=(long long)R-L;
				L=R;
			}
		}
		printf("Case #%d:\n",CASE);
		int m,x,y;
		scanf("%d",&m);
		while(m--){
			scanf("%d%d",&x,&y);
			int GCD=RMQ(x,y);
			printf("%d %lld\n",GCD,MAP_cnt[GCD]);
		}	
	}
	return 0;
}


你可能感兴趣的:(acm算法)