CF1956D Nene and the Mex Operator 讲题综合版
题意:
操作方法:
Choose two integers
也就是说选一段
根据
When
a_i=0 , the sum can hitn^2 with makinga_i=n at last. Construction:
//! a function which sets a_1 ... a_k into k.
function solve(k):
if k is 1:
operate [1,1]
return
end if
solve(k-1);
for i in [k-2, ..., 1]:
operate [1,i] //! this sets a_1 ... a_i into 0
solve(i)
//! here, a should be [i, i, ..., i, i+1, i+2, ..., k-1, 0]
end for
//! here, a should be [1, 2, 3, ..., k-1, 0]
operate [1,k]
return
Here,
solve(k)will take about2^k operations.
根据如上信息,我们可以找到一些思路:
用
一个区间假设就算离散得很严重,但由于是找最小非负整数,这个最小非负整数一定会满足
现在面临
A.
一个区间一旦执行操作,就必须变成总和为
一个区间至少知道怎么算,也知道一定能把总和变成
全都变成
link
B.
我们显然知道对于任意正整数 1 100 2 1 中
C.
考虑区间 dp,
那么就可以按照思路,写出求
#include <bits/stdc++.h>
using namespace std;
int n;
int dp[20][20]; // 段 l, r 能达到的最大值。
int a[20];
int MAX__(int a, int b, int c, int d) {
return max(max(a, b), max(c, d));
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
dp[i][i] = max(a[i], 1);
}
for (int len = 2; len <= n; len++) {
for (int l = 1; l <= n && l + len - 1 <= n; l++) { // 分段起点
int r = l + len - 1; // 分段终点
dp[l][r] = len * len;
for (int k = l; k <= r - 1; k++) { // 中断点。
int lenl = k - l + 1; // 左边区间的长度;
int lenr = len - lenl; // 右边区间的长度。
dp[l][r] = max(dp[l][r], MAX__(lenl * lenl + lenr * lenr, dp[l][k] + lenr * lenr, lenl * lenl + dp[k + 1][r], dp[l][k] + dp[k + 1][r]));
}
}
}
cout << dp[1][n] << "\n"; // sum_max
return 0;
}
只要合成操作就行了。
亿点点代码:
#include <bits/stdc++.h>
using namespace std;
int n;
int dp[20][20]; // 段 l, r 能达到的最大值。
int a[20];
struct Node{
queue<int> l;
queue<int> r; // 操作序列
} __opertor__[20][20];
int MAX__(int a, int b, int c, int d) {
return max(max(a, b), max(c, d));
}
vector <int> lans;
vector <int> rans;
int op[20];
void solve(int l, int r) { // 将 l, r 区间操作成 k^2。 [l,r] 都变成 k
int k = (r - l + 1);
if (k == 1) {
if (op[l] != 0) {
lans.push_back(l);
rans.push_back(l);
op[l] = 0;
lans.push_back(l);
rans.push_back(l);
op[l] = 1;
} else {
lans.push_back(l);
rans.push_back(l);
op[l] = 1;
}
return ;
}
//solve(l + 1, r)
if (op[l] != 0) {
lans.push_back(l);
rans.push_back(l);
op[l] = 0;
}
for (int i = l + 1; i <= r; i++) {
//cout << i << " " << r << "==\n";
solve(i, r);
}
for (int i = 1; i <= r; i++) {
op[i] = k;
}
lans.push_back(l);
rans.push_back(r);
return ;
/*
for (int i = 1, u = l; i <= k; i++, u++) {
op[i] = a[u];
}
for (int i = k - 1, start = 1; k >= 1; k--, start++) { // 目标数:i,操作位置:[start,k]
for (int j = start; j <= k; j++) {
if (op[i] != 0) {
op[i] = 0;
lans.push_back(j + l - 1);
rans.push_back(j + l - 1);
}
}
}
*/
//return ;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
dp[i][i] = max(a[i], 1);
if (a[i] == 0) {
__opertor__[i][i].l.push(i);
__opertor__[i][i].r.push(i);
}
}
for (int len = 2; len <= n; len++) {
for (int l = 1; l <= n && l + len - 1 <= n; l++) { // 分段起点
int r = l + len - 1; // 分段终点
dp[l][r] = len * len;
__opertor__[l][r].l.push(l);
__opertor__[l][r].r.push(r);
for (int k = l; k <= r - 1; k++) { // 中断点。
int lenl = k - l + 1; // 左边区间的长度;
int lenr = len - lenl; // 右边区间的长度。
dp[l][r] = max(dp[l][r], MAX__(lenl * lenl + lenr * lenr, dp[l][k] + lenr * lenr, lenl * lenl + dp[k + 1][r], dp[l][k] + dp[k + 1][r]));
if (dp[l][r] == lenl * lenl + lenr * lenr) {
while (!__opertor__[l][r].l.empty()) { /////////////////////////1
__opertor__[l][r].l.pop();
__opertor__[l][r].r.pop();
}
__opertor__[l][r].l.push(l);
__opertor__[l][r].l.push(k);
__opertor__[l][r].l.push(k + 1);
__opertor__[l][r].l.push(k);
} else if (dp[l][r] == dp[l][k] + lenr * lenr) { ///////////////////2
while (!__opertor__[l][r].l.empty()) {
__opertor__[l][r].l.pop();
__opertor__[l][r].r.pop();
}
queue<int> ok1, ok2;
while (!ok1.empty()) {ok1.pop();} while (!ok2.empty()) {ok2.pop();}
while (!__opertor__[l][k].l.empty()) {
__opertor__[l][r].l.push(__opertor__[l][k].l.front());
__opertor__[l][r].r.push(__opertor__[l][k].r.front());
ok1.push(__opertor__[l][k].l.front());
ok2.push(__opertor__[l][k].r.front());
__opertor__[l][k].l.pop();
__opertor__[l][k].r.pop();
}
while (!ok1.empty()) {
__opertor__[l][k].l.push(ok1.front());
__opertor__[l][k].r.push(ok2.front());
ok1.pop();
ok2.pop();
}
__opertor__[l][r].l.push(k + 1);
__opertor__[l][r].r.push(r);
} else if (dp[l][r] == lenl * lenl + dp[k + 1][r]) { /////////////////////3
while (!__opertor__[l][r].l.empty()) {
__opertor__[l][r].l.pop();
__opertor__[l][r].r.pop();
}
queue<int> ok1, ok2;
while (!ok1.empty()) {ok1.pop();} while (!ok2.empty()) {ok2.pop();}
while (!__opertor__[k + 1][r].l.empty()) {
__opertor__[l][r].l.push(__opertor__[k + 1][r].l.front());
__opertor__[l][r].r.push(__opertor__[k + 1][r].r.front());
ok1.push(__opertor__[k + 1][r].l.front());
ok2.push(__opertor__[k + 1][r].r.front());
__opertor__[k + 1][r].l.pop();
__opertor__[k + 1][r].r.pop();
}
while (!ok1.empty()) {
__opertor__[k + 1][r].l.push(ok1.front());
__opertor__[k + 1][r].r.push(ok2.front());
ok1.pop();
ok2.pop();
}
__opertor__[l][r].l.push(l);
__opertor__[l][r].r.push(k);
} else if (dp[l][r] == dp[l][k] + dp[k + 1][r]) { /////////////////4
while (!__opertor__[l][r].l.empty()) {
__opertor__[l][r].l.pop();
__opertor__[l][r].r.pop();
}
queue<int> ok1, ok2;
while (!ok1.empty()) {ok1.pop();} while (!ok2.empty()) {ok2.pop();}
while (!__opertor__[l][k].l.empty()) {
__opertor__[l][r].l.push(__opertor__[l][k].l.front());
__opertor__[l][r].r.push(__opertor__[l][k].r.front());
ok1.push(__opertor__[l][k].l.front());
ok2.push(__opertor__[l][k].r.front());
__opertor__[l][k].l.pop();
__opertor__[l][k].r.pop();
}
while (!ok1.empty()) {
__opertor__[l][k].l.push(ok1.front());
__opertor__[l][k].r.push(ok2.front());
ok1.pop();
ok2.pop();
}
//--------
while (!ok1.empty()) {ok1.pop();} while (!ok2.empty()) {ok2.pop();}
while (!__opertor__[k + 1][r].l.empty()) {
__opertor__[l][r].l.push(__opertor__[k + 1][r].l.front());
__opertor__[l][r].r.push(__opertor__[k + 1][r].r.front());
ok1.push(__opertor__[k + 1][r].l.front());
ok2.push(__opertor__[k + 1][r].r.front());
__opertor__[k + 1][r].l.pop();
__opertor__[k + 1][r].r.pop();
}
while (!ok1.empty()) {
__opertor__[k + 1][r].l.push(ok1.front());
__opertor__[k + 1][r].r.push(ok2.front());
ok1.pop();
ok2.pop();
}
}
}
}
}
/*
while (!__opertor__[1][n].l.empty()) {
cout << __opertor__[1][n].l.front() << " " << __opertor__[1][n].r.front() << "\n";
__opertor__[1][n].l.pop();
__opertor__[1][n].r.pop();
}
*/
while (!__opertor__[1][n].l.empty()) {
//cout << __opertor__[1][n].l.front() << " - " << __opertor__[1][n].r.front() << "\n";
for (int i = 1; i <= n; i++) {
op[i] = a[i];
}
solve(__opertor__[1][n].l.front(), __opertor__[1][n].r.front()); // 万能公式。
__opertor__[1][n].l.pop();
__opertor__[1][n].r.pop();
}
cout << dp[1][n] << " "; // sum_max
cout << lans.size() << "\n";
for (int i = 0; i < lans.size(); i++) {
cout << lans[i] << " " << rans[i] << "\n";
}
return 0;
}
性能: