0%

P5665划分

在CSP结束近一年后,终于听人讲了这道题

惭愧啊 惭愧

36pts

一个考场都没想出来的$n^3$暴力DP

设$f_{i,j}$为考虑到$i$这个点,$i$所在块的起点为$j$,最小的时间代价

更新方法就是把$k$从$1$到$j-1$枚举,当满足题目条件($\sum\limits_{l=k}^{j-1}{a_l}\leq\sum\limits_{l=j}^{i}{a_l}$)时,$f_{i,j}=\min\{ {f_{j-1,k}+(\sum\limits_{l=j}^{i}{a_l})^2}\}$

统计答案时,$ans=\min_{i=1}^{n}{ \{f_{n,i}\} }$

记得开long long

Code
1
2
3
4
5
6
7
8
9
10
11
12
memset(f, 0x3f, sizeof f),
f[0][0] = 0;
for (register int i = 1; i <= n; ++i) //枚举运算到的位置
for (register int j = 0; j <= i; ++j) { //枚举断点
if (!j || j == 1)
f[i][j] = sum[i] * sum[i];
for (register int k = 1; k <= j - 1; ++k) //枚举比j更早的断点
if (sum[j - 1] - sum[k - 1] <= sum[i] - sum[j - 1])
f[i][j] = min(f[i][j], f[j - 1][k] + (sum[i] - sum[j - 1]) * (sum[i] - sum[j - 1]));
}
for (register int i = 1; i <= n; ++i)
ans = min(ans, f[n][i]);

64pts

首先由完全平方公式可以推出,$(\sum\limits_{i=1}^{n}a_i)^2\geq\sum\limits_{i=1}^{n}a_i^2$,当且仅当$a_i=0$时等号成立

所以如果想让总代价更小,要尽量多分块

用$f_i$表示将$1$到$i$按最优方案划分后的时间代价,$g_i$表示将$1$到$i$按最优方案划分后,最后一段的的开头为$k$,有式子

同时,显然已经划分过的段不会再参与到之后的划分中,所以令$top$表示上一次划分到的块的终点,下次划分时从$top$开始枚举即可

每次$j$从$top + 1$枚举到$i-1$,判断满足$\sum\limits_{j=top+1}^{i-1}{a_j}\geq g_j$,更新$f_i$,$g_i$和$top$即可

答案$ans=f_n$

Code
1
2
3
4
5
6
7
8
9
for (register int i = 1; i <= n; ++i) { //枚举运算到的位置
f[i] = 99999999999999999;
for (register int j = top; j < i; ++j) { //枚举断点
if (sum[i] - sum[j] >= g[j])
f[i] = min(f[i], f[j] + (sum[i] - sum[j]) * (sum[i] - sum[j])),
g[i] = sum[i] - sum[j],
top = j;
}
}

有的题解是用$g_i$表示满足条件的最大的$j$,即$g_i=\max\limits_{\sum\limits_{l=g_j}^{j}{a_l}\leq\sum\limits_{l=j+1}^{i}{a_l} }{ \{j\} }$

88pts

对于判断合法的式子$\sum\limits_{l=g_j+1}^{j}{a_l}\leq\sum\limits_{l=j+1}^{i}{a_l}$,将其用前缀和表示出来,即为$sum_{j}-sum_{g_j}\leq sum_i-sum_j$

合并同类项,可得$2\cdot sum_j-sum_{g_j}\leq s_i$

令$d(j)=2sum_j-sum_{g_j}$,$g_i$表示满足条件的最大的$j$,即$g_i=\max\limits_{\sum\limits_{l=g_j}^{j}{a_l}\leq\sum\limits_{l=j+1}^{i}{a_l} }{ \{j\} }$

可以设想一下,如果$\exists x<y,\ d(x)\leq s_i,\ d(y)\leq s_i$,按照分块尽量少的原则,肯定优先选择$y$

所以$g_i$具有单调性

因此我们可以维护一个单调队列,储存有用的决策点,其中$g_i$单调递增

当队首满足条件$d(q_{head})\leq sum_i$时,根据分块尽量少的原则,选择最后的满足条件的$q_{head}$更新$g_i$

当队尾不满足$d(q_{tail})< d(i)$时,删除队尾

最后把当前点加入队列中

统计答案时,根据$g_i$往前跳即可

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
for (register int i = 1; i <= n; ++i) {
while (l < r && sum[queue[l + 1]] - sum[pre[queue[l + 1]]] + sum[queue[l + 1]] <= sum[i])
++l;
pre[i] = queue[l];
while (l < r && sum[queue[r]] - sum[pre[queue[r]]] + sum[queue[r]] >= sum[i] - sum[pre[i]] + sum[i])
--r;
queue[++r] = i;
}
int now = n;
__int128 ans = 0;
while (now)
ans += (sum[now] - sum[pre[now]]) * (sum[now] - sum[pre[now]]),
now = pre[now];

100pts

把$type=1$的点写上即可

记得写高精或者__int128

省空间大法:$sum$前缀和数组重复使用

以及需要$O2$优化

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma G++ optimize(2)
#pragma G++ optimize(3)
#pragma G++ optimize("Ofast")
#pragma G++ optimize("inline")
#pragma G++ optimize("-fgcse")
#pragma G++ optimize("-fgcse-lm")
#pragma G++ optimize("-fipa-sra")
#pragma G++ optimize("-ftree-pre")
#pragma G++ optimize("-ftree-vrp")
#pragma G++ optimize("-fpeephole2")
#pragma G++ optimize("-ffast-math")
#pragma G++ optimize("-fsched-spec")
#pragma G++ optimize("unroll-loops")
#pragma G++ optimize("-falign-jumps")
#pragma G++ optimize("-falign-loops")
#pragma G++ optimize("-falign-labels")
#pragma G++ optimize("-fdevirtualize")
#pragma G++ optimize("-fcaller-saves")
#pragma G++ optimize("-fcrossjumping")
#pragma G++ optimize("-fthread-jumps")
#pragma G++ optimize("-funroll-loops")
#pragma G++ optimize("-fwhole-program")
#pragma G++ optimize("-freorder-blocks")
#pragma G++ optimize("-fschedule-insns")
#pragma G++ optimize("inline-functions")
#pragma G++ optimize("-ftree-tail-merge")
#pragma G++ optimize("-fschedule-insns2")
#pragma G++ optimize("-fstrict-aliasing")
#pragma G++ optimize("-fstrict-overflow")
#pragma G++ optimize("-falign-functions")
#pragma G++ optimize("-fcse-skip-blocks")
#pragma G++ optimize("-fcse-follow-jumps")
#pragma G++ optimize("-fsched-interblock")
#pragma G++ optimize("-fpartial-inlining")
#pragma G++ optimize("no-stack-protector")
#pragma G++ optimize("-freorder-functions")
#pragma G++ optimize("-findirect-inlining")
#pragma G++ optimize("-fhoist-adjacent-loads")
#pragma G++ optimize("-frerun-cse-after-loop")
#pragma G++ optimize("inline-small-functions")
#pragma G++ optimize("-finline-small-functions")
#pragma G++ optimize("-ftree-switch-conversion")
#pragma G++ optimize("-foptimize-sibling-calls")
#pragma G++ optimize("-fexpensive-optimizations")
#pragma G++ optimize("-funsafe-loop-optimizations")
#pragma G++ optimize("inline-functions-called-once")
#pragma G++ optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#ifdef DEBUG
#define __int128 long long
#endif
using std::min;
int n, type, l, r, m, p, queue[40000001], pre[40000001], x, y, z;
__int128 sum[40000001];

template<class I>
inline void write(I a) {
if (a > 9)
write(a / 10);
putchar(a % 10 + '0');
}

int main(void) {
scanf("%d%d", & n, & type);
if (!type)
for (register int i = 1; i <= n; ++i)
scanf("%lld", & sum[i]),
sum[i] += sum[i - 1];
else {
scanf("%d%d%d%lld%lld%d", & x, & y, & z, & sum[1], & sum[2], & m);
for (register int i = 3; i <= n; ++i)
sum[i] = (1LL * x * sum[i - 1] + 1LL * y * sum[i - 2] + z) & ((1 << 30) - 1);
int j = 1;
for (register int i = 1; i <= m; ++i) {
scanf("%d%d%d", & p, & l, & r);
for (; j <= p; ++j)
sum[j] = sum[j] % (r - l + 1ll) + l,
sum[j] += sum[j - 1];
}
}
l = r = 0;
for (register int i = 1; i <= n; ++i) {
while (l < r && sum[queue[l + 1]] - sum[pre[queue[l + 1]]] + sum[queue[l + 1]] <= sum[i])
++l;
pre[i] = queue[l];
while (l < r && sum[queue[r]] - sum[pre[queue[r]]] + sum[queue[r]] >= sum[i] - sum[pre[i]] + sum[i])
--r;
queue[++r] = i;
}
int now = n;
__int128 ans = 0;
while (now)
ans += (sum[now] - sum[pre[now]]) * (sum[now] - sum[pre[now]]),
now = pre[now];
write(ans);
return 0;
}

完结!

全体起立!

坚持原创技术分享, 您的支持将鼓励我继续创作!