P5665 [CSP-S2019] 划分

P5665 CSP-S2019划分

f[i][j] 表示前i个数,最后的位置为j的最小平方和,s为前缀和
f[i][j] = (s[i]-s[j])**2 + min:f[j][k] ,其中si-sj>=sj-sk,0<=k<j
结论::::::::f(i,j)有解时f(i,j-1)>=f(i,j) (打表)
g(i)为最大的j使...则2sj-s{g(j)}<=si:使用单调队列优化
最后转化成递推...

点击查看代码

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MOD 0x3fffffff
const int N = 4e7 + 5, M = 1e5 + 5;
typedef long long LL; typedef __int128_t LLL;
int n, type, a[N], q[N], g[N];
int p[M], l[M], r[M], b[N];
LL sum[N];
inline LL d(int x) { return sum[x] - sum[g[x]]; }
int main() {
	scanf("%d%d", &n, &type);
	if(type) {
		int x, y, z, m;
		scanf("%d%d%d%d%d%d", &x, &y, &z, b+1, b+2, &m);
		for(int i = 1; i <= m; i ++) scanf("%d%d%d", p + i, l + i, r + i);
		for(int i = 3; i <= n; i ++) b[i] = (LL(x) * b[i-1] + LL(y) * b[i-2] + z) & MOD;
		for(int i = 1; i <= m; i ++)
			for(int j = p[i-1]+1; j <= p[i]; j ++) a[j] = b[j] % (r[i] - l[i] + 1) + l[i];
	} else for(int i = 1; i <= n; i ++) scanf("%d", a + i);
	for(int i = 1; i <= n; i ++) sum[i] = sum[i-1] + a[i];
	int hh = 0, tt = 0;
	for(int i = 1; i <= n; i ++) {
		while(hh < tt && d(q[hh + 1]) + sum[q[hh + 1]] <= sum[i]) hh ++;
		g[i] = q[hh];
		while(hh < tt && d(q[tt]) + sum[q[tt]] >= d(i) + sum[i]) tt --;
		q[++ tt] = i;
	}
	int now = n;
	LLL ans = 0, tmp = 1;
	while(now) tmp=d(now),tmp*=tmp, ans += tmp, now = g[now];
	static int dig[99]; tmp = 0;
	do { dig[++ tmp] = ans % 10, ans /= 10; } while(ans);
	while(tmp) putchar(dig[tmp --] ^ 48);
	return 0;
}
posted @ 2022-09-29 13:50  azzc  阅读(28)  评论(0编辑  收藏  举报