hdu 5289 Assignment 二分+rmq

鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5289

Assignment

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 332    Accepted Submission(s): 169


Problem Description
Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special task to some staffs who were in the same group. In a group, the difference of the ability of any two staff is less than k, and their numbers are continuous. Tom want to know the number of groups like this.
 

Input
In the first line a number T indicates the number of test cases. Then for each case the first line contain 2 numbers n, k (1<=n<=100000, 0<k<=10^9),indicate the company has n persons, k means the maximum difference between abilities of staff in a group is less than k. The second line contains n integers:a[1],a[2],…,a[n](0<=a[i]<=10^9),indicate the i-th staff’s ability.
 

Output
For each test,output the number of groups.
 

Sample Input
2 4 2 3 1 2 4 10 5 0 3 4 5 2 1 6 7 8 9
 

Sample Output
5 28
Hint
First Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
 


題意:

問有多少區間段,最大小值差<k。


做法: 

枚舉右端點,很明顯 區間越大,最大小值差越大,所以有線性關係。所以可以二分。找到差值小於k的點,這個點到右端點之間所有點都可以做爲左端點。

線段樹和樹狀數組都可能超時,離線最大小值計算最穩的就是RMQ了。


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100100;
int n,query;
int A[MAXN];
int FMin[MAXN][20],FMax[MAXN][20];

void Init(){
	int i,j;
	for(i=1;i<=n;i++)
		FMin[i][0]=FMax[i][0]=A[i];
	for(i=1;(1<<i)<=n;i++){   //按區間長度遞增順序遞推 
		for(j=1;j+(1<<i)-1<=n;j++){   //區間起點 
			FMin[j][i]=min(FMin[j][i-1],FMin[j+(1<<(i-1))][i-1]);
			FMax[j][i]=max(FMax[j][i-1],FMax[j+(1<<(i-1))][i-1]);
		}
	} 
}

int Query(int l,int r){
	int k=(int)(log(double(r-l+1))/log((double)2));
	return max(FMax[l][k],FMax[r-(1<<k)+1][k]);
}
int Query2(int l,int r){
	int k=(int)(log(double(r-l+1))/log((double)2));
	return min(FMin[l][k],FMin[r-(1<<k)+1][k]);
}
int main(){
	int a,b;
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int k;
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++) scanf("%d",&A[i]);
		Init();
		int lll=1;
		__int64 ans=0;
		for(int i=1;i<=n;i++)
		{
			int l=lll;
			int r=i;
			while(l<=r)
			{
				int mid=(l+r)/2;
				int low=Query2(mid,i);
				int hig=Query(mid,i);
				int tt=hig-low;

				if(tt>=k)
					l=mid+1;
				else if(tt<k)
					r=mid-1;
			}

			lll=l;
			ans+=i-l+1;
		}

		printf("%I64d\n",ans);
	}
	return 0;
}





發佈了240 篇原創文章 · 獲贊 3 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章