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;
}