六月11号补题日记:Atorder Beginner Contest 305

KYOCERA Programming Contest 2023(AtCoder Beginner Contest 305)

D题:二分答案:

读这个题目的时候我就意识到了二分:

学会了lower_bound和upper_bound,低级的就是多了一个相等

题意:这个题意也是非常经典的题意,这个的题意非常的简单,我刚开始还没有读懂,有些题目可能上来,说一些没有用的话,其实题意很简单

1怎样做:这里涉及到一个非常经典的问题:早饭的时候我总共是偷玩了A[time[早饭]]分钟的游戏,午饭时我总共是偷偷的玩了A[time[早饭]]分钟的游戏,现在我想知道在早饭和中午饭之间的一次上厕所的时间是time[上厕所],我想知道截至到上厕所,我一共是偷玩了多少时间A[time[上厕所]](time都是知道的):A[time[早饭]] + (time[午饭] - time[wc])*  (A[午饭] - A[早饭]),因为这个东西是线性的

2为什么:二分答案的话能够用很短的时间找到位置

3下次如何想起来:二分答案的题目,往往是非常经典的题目:

4这个是累计区间问题

5注意一下这个题目的代码,A[i]往后面延迟了一位,a[i]睡眠时间对应的是A[i + 1]的睡眠时间

#include 
#include 
using namespace std;

const int N = 2e5 + 10;
long long a[N],A[N];
int n;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	
	for(int i = 1;i <= n;i ++) cin >> a[i];
	
	for(int i = 1;i <= n;i ++){
		if(i % 2 != 0) A[i] = A[i - 1] + a[i] - a[i - 1];
		else A[i] = A[i - 1];
	}
	int cnt;
	cin >> cnt;
	
	while(cnt --){
		int l,r;
		cin >> l >> r;
		
		int i = upper_bound(a + 1,a + n,l) - a - 1;
		long long L = A[i] + (l - a[i])* (A[i + 1] - A[i])/(a[i + 1] - a[i]);
		
		int j = upper_bound(a + 1,a + n,r) - a - 1;;
		long long R = A[j] + (r - a[j])* (A[j + 1] - A[j])/(a[j + 1] - a[j]);
		cout << R - L << endl;
	}	
	return 0;
}

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