专栏文章

题解:P1982 [NOIP2013 普及组] 小朋友的数字

P1982题解参与者 2已保存评论 1

文章操作

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

当前评论
1 条
当前快照
1 份
快照标识符
@miqkdyrg
此快照首次捕获于
2025/12/04 06:14
3 个月前
此快照最后确认于
2025/12/04 06:14
3 个月前
查看原文

题解:P1982 [NOIP2013 普及组] 小朋友的数字

思路

显然,这道题目需要先对于每一个节点求出最大子段和,做一遍 dp。
接下来,只需要线性扫描,求出每一个小朋友分数的前缀最大值即可。
时间复杂度 O(n)O(n)
需要注意的是本题的数据范围,需要开 __int128

AC Code

CPP
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
__int128 read() {
	__int128 x = 0;
    int w = 0; 
    char ch;
    while (!isdigit(ch)) { 
    	w |= ch == '-'; ch = getchar(); 
    }
    while (isdigit(ch)) 
    	x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    return w ? -x : x;
}

void out(__int128 x) {
    if (x < 0) {putchar('-');x *= -1;}
	if (x > 9) out(x / 10);
	putchar(x % 10 + '0');
}

long long n;
__int128 p,a[maxn],dp[maxn],f[maxn],ans[maxn],anss;

inline __int128 abss(__int128 x){
	if(x>=0)return x;
	return -x;
}

int main(){
	scanf("%lld",&n);
	p = read();
	for(long long i = 1;i <= n;i++) a[i] = read();
	f[1] = a[1],ans[1] = a[1];
	for(long long i = 2;i <= n;i++){
		f[i] = max(a[i],f[i-1]+a[i]);
		ans[i] = max(ans[i-1],f[i]);
	}
	if(n == 1){
		out(ans[1]%p);
		return 0;
	}
	dp[1] = ans[1],dp[2] = ans[1] + ans[1];
	anss = max(dp[1],dp[2]);
	for(long long i = 3;i <= n;i++) dp[i] = max(dp[i-1],dp[i-1]+ans[i-1]),anss = max(dp[i],anss);
	if(anss < 0) printf("-");
	__int128 o = abss(anss)%p;
	out(o);
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...