HDU 5289

发现枚举+二分更好!

我做得复杂了,竟然两个都是从左边开始枚举。找最大最小用ST算法吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;

const int MAX=100050;

int f_min[MAX][20];
int f_max[MAX][20];
int num[MAX],n,dif;

void pre_init(){
	int k=(int)(log((double)n)/log(2.0));
	for(int i=0;i<n;i++) f_min[i][0]=num[i],f_max[i][0]=num[i];
	for(int j=1;j<=k;j++){
		for(int i=0;i + (1 << j) - 1<n;i++){
			f_min[i][j]=min(f_min[i][j-1],f_min[i+(1<<(j-1))][j-1]);
			f_max[i][j]=max(f_max[i][j-1],f_max[i+(1<<(j-1))][j-1]);
		}
	}
}

int find_min(int i,int j){
	int k = (int)(log(double(j-i+1)) / log(2.0));
	return min(f_min[i][k], f_min[j - (1<<k) + 1][k]);
}

int find_max(int i,int j){
	int k = (int)(log(double(j-i+1)) / log(2.0));
	return max(f_max[i][k], f_max[j - (1<<k) + 1][k]);
}

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&dif);
		for(int i=0;i<n;i++)
			scanf("%d",&num[i]);
		pre_init();
		LL ans=0;
		int l=0,r=0;
		int dmin=num[0],umax=num[0]; bool flag=true;
		while(l<n&&r<n){
			if(flag){
				while(r<n){
					r++;
					if(r==n){
						r--;
						break;
					}
					dmin=find_min(l,r);
					umax=find_max(l,r);
					if(umax-dmin>=dif){
						r--;
						break;
					}
				}
			//	cout<<"true:"<<l<<" "<<r<<endl;
				flag=false;
				ans+=r-l+1;
			}
			else{
				while(l<=r){
					l++;
					if(l>r){
						break;
					}
					if(dmin!=find_min(l,r)||umax!=find_max(l,r)){
						break;
					}
					else{
						ans+=r-l+1;
					}
				}
			//	cout<<"false:"<<l<<" "<<r<<endl;
				flag=true;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

  

posted @ 2015-09-09 23:33  chenjunjie1994  阅读(226)  评论(0编辑  收藏  举报