2019 ICPC徐州网络赛 E. XKC's basketball team(二分)

计蒜客题目链接:https://nanti.jisuanke.com/t/41387

题目大意:给定一组无序序列,从第一个数开始,求最远比这个数大m的数,与这个数之间相隔多少数字?如果没有输出-1,否则输出间隔了多少数字。

题解:从后往前遍历,在遍历的同时维护一个递增队列,若当前的数大于队尾就进队,否则从该队列中二分找最小的比自己大至少  的数,二者之间的距离即为答案,这里我用vector模拟这个队列。若当前数小于队尾,那这个数一定没有队尾的数优,因为它既比队尾的数靠前,又比它小。

 

AC代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int main(){
	int n;
	long long m;
	scanf("%d%lld",&n,&m);
	int arr[n+1];
	for(int i = 0;i<n;i++){
		scanf("%lld",&arr[i]);
	}
	vector<long long int> increase_seq;//存储递增序列 
	map<long int,long int> index;//存储递增序列元素的索引 
	vector<long long int > ans;
	for(long long int i = n-1;i>=0;i--){
		if(i == n-1){
			increase_seq.push_back(arr[i]); //遍历的第一个数一定放入队列 
			index[arr[i]] = i;
			ans.push_back(-1); 
		}
		else{
			if(increase_seq[increase_seq.size() -1] < arr[i]){
				increase_seq.push_back(arr[i]); 
				index[arr[i]] = i; 
				ans.push_back(-1); 
			}
			else{
				long long int t = arr[i] + m;
				int v = lower_bound(increase_seq.begin(),increase_seq.end() ,t ) - increase_seq.begin() ;
				if(v == increase_seq.size() ){//在队列中二分 
					ans.push_back(-1); 
				}
				else{
					ans.push_back(index[increase_seq[v]] - i -1); 
				}
			}
		}
	}
	for(int i = ans.size() -1;i>=0;i--){
		if(i == ans.size()-1){
			printf("%lld",ans[i]);
			continue;
		}
		printf(" %lld",ans[i]);
	}
	return 0;
}

 

posted @ 2019-09-11 22:55  AaronChang  阅读(127)  评论(0编辑  收藏  举报