社区讨论

神金代码30pts只AC#1,4,5求调教

P3957[NOIP 2017 普及组] 跳房子参与者 3已保存回复 12

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
12 条
当前快照
1 份
快照标识符
@m0f3hhtn
此快照首次捕获于
2024/08/29 17:40
2 年前
此快照最后确认于
2025/11/05 00:29
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
#define N 5000000
#define INF 1145141919810
#define int1 long long
using namespace std;
int1 n,d,k,l,r,mid,i,x[N + 5],s[N + 5],dp[N + 5],q[N + 5],head,tail,sum;
int1 read(){
	int1 x = 0,f = 1;
	char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-'){
			f = -1;
		}
		ch = getchar();
	}
	while(isdigit(ch)){
		x = (x << 1) + (x << 3) + (ch ^ '0');
		ch = getchar();
	}
	return x * f;
}
char getc(int1 x){//1:数字    2:小写    4:大写    8:字符    16:空格
	char ch = getchar();
	while(!(((x & 1) && ch >= '0' && ch <= '9') || ((x & 2) && ch >= 'a' && ch <= 'z') || 
	((x & 4) && ch >= 'A' && ch <= 'Z') || ((x & 8) && ch != ' ' && ch != '\n' && ch != '\0') || ((x & 16) && ch != '\n' && ch != '\0'))){
		ch = getchar();
	}
	return ch;
}
void uprint(int1 x){
  	if(x > 9){
    	uprint(x / 10);
  	}
  	putchar(x % 10 ^ 48);
  	return ;
}
void print(int1 x){
  	if(x < 0){
    	putchar('-');
    	x = -x;
	}
	uprint(x);
	return ;
}
void ps(int1 x){
	print(x);
	putchar(' ');
	return ;
}
void pe(int1 x){
	print(x);
	putchar('\n');
	return ;
}
bool check(){
	tail = 1,head = 1,q[head] = 0;
	int1 maxn = -INF;
	for(int1 i = 1,j = 1; i <= n; i++){
		dp[i] = -INF;
		int1 l = lower_bound(x,x + n + 1,x[i] - d - mid) - x,r = min(i,(int1)(upper_bound(x,x + n + 1,x[i] - d + mid) - x)) - 1;//i这个点可以由[l,r]这个区间内的点跳过来
		if(l <= r){
			while(head <= tail && q[head] < l){//弹出不在区间内的元素
				head++;
			}
			for(; j <= r; j++){//将在区间内的元素加入
				while(head <= tail && dp[j] >= dp[q[tail]]){//弹出答案更劣的队尾
					tail--;
				}
				q[++tail] = j;//加入
			}
		}
		if(head <= tail){//如果队列不为空
			dp[i] = dp[q[head]] + s[i];//更新答案
		}
//		ps(dp[i]);
		maxn = max(maxn,dp[i]);
	}
//	pe(maxn);
	return (maxn >= k);
}
int main(){
	n = read(),d = read(),k = read();
	for(i = 1; i <= n; i++){
		x[i] = read(),s[i] = read();
		if(s[i] > 0){
			sum += s[i];
		}
	}
	if(sum < k){//无解
		pe(-1);
		return 0;
	}
	l = 0,r = x[n];
	while(l < r){
		mid = (l + r) >> 1;
		if(check()){
			r = mid;
		}else{
			l = mid + 1;
		}
	}
	pe(r);
	return 0;
}
/*
7 4 10
2 6
5 -3
10 3
11 -3
13 1
17 6
20 2

7 4 20
2 6
5 -3
10 3
11 -3
13 1
17 6
20 2
*/

回复

12 条回复,欢迎继续交流。

正在加载回复...