CSP2019 D2T2 划分 (单调队列DP)

题目

洛谷传送门

题解

就是这道题搞我退役考场上写了n^2 64分,结果爆成8-12分。直接GG。
考场上想到正解的写法被自己否决了

题解传送门(看到这道送我退役的题目⑧太想写题解)

六行 O ( n 2 ) O(n^2) DP 88 88 分代码

	for(int i = 1; i <= n; ++i) a[i] += a[i-1];
	f[0] = d[0] = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = i; j >= 1; --j) {
			if(a[i]-a[j-1]<d[j-1]) continue;
			d[i] = a[i]-a[j-1], f[i] = f[j-1] + d[i]*d[i];
			break;
		}
	printf("%lld\n", f[n]);

同样六行 O ( n ) O(n) DP 100 100 分代码

#include <bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &x) {
	char ch; while(!isdigit(ch=getchar()));
	for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
}
typedef long long LL;
const int MAXN = 40000005;
const int MOD = 1073741824;
int n, ty, stk[50], indx;
LL a[MAXN];
int q[MAXN], pre[MAXN], s, t;

int main () {
	read(n), read(ty);
	if(!ty) for(int i = 1; i <= n; ++i) read(a[i]);
	else {
		int x, y, z, m;
		read(x), read(y), read(z), read(a[1]), read(a[2]), read(m);
		for(int i = 3; i <= n; ++i) a[i] = (x*a[i-1] + y*a[i-2] + z) % MOD;
		for(int i = 1, p, l, r, j = 1; i <= m; ++i) {
			read(p), read(l), read(r);
			while(j <= p) a[j] = a[j] % (r-l+1) + l, ++j;
		}
	}
	for(int i = 1; i <= n; ++i) a[i] += a[i-1];
	q[s=t=0] = 0;
	for(int i = 1; i <= n; ++i) {
		while(s < t && a[q[s+1]]-a[pre[q[s+1]]]+a[q[s+1]] <= a[i]) ++s;
		pre[i] = q[s];
		while(s < t && a[q[t]]-a[pre[q[t]]]+a[q[t]] >= a[i]-a[pre[i]]+a[i]) --t;
		q[++t] = i;
	}
	__int128 ans = 0, tmp; int now = n;
	while(now) { tmp = a[now]-a[pre[now]]; ans += tmp*tmp; now = pre[now]; }
	while(ans) { stk[++indx] = ans%10; ans/=10; }
    while(indx) putchar('0'+stk[indx--]); puts("");
}

水题送我退役。

粗鄙之语

发布了367 篇原创文章 · 获赞 239 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/103324428