D
- 真感觉比E跟F还要难一点,也可能是这部分比较薄弱,总之这一块是一定要多练的。
- 状压+方案数dp,赛时看到处理回文就直接去看E了,结果回文长度最多才10???不过赛后补的时候状压竟然写了10分钟,感觉很不好,得练。还有这个dp方案也很有意思,我们每次只需要看到i的前k - 1项即可,如果这一串不是回文,那就一定能确定可以从之前不含回文的状态中转移过来,一开始想的时候没有迅速反应过来,可能对题干“定长回文串”的条件没有很理解。
E
- 题意还是昨天说的题意,其实这个题意很贴单调栈,看的出来这些小的点还不是很熟练,之前还试着给ll讲过一个单调栈题来着,现在看来也是蜻蜓点水,还得多练才行。
F
- 贪心,关键是找到一个合适的递推过程。此题可以从d全1的状态来递推,这样可以迅速找到每一项对应的增量,并依照这个进行更改。
补充
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <random>
#include <bitset>
#include <tuple>
#include <iterator>
#define int long long
typedef std::pair<int, int> PII;
std::mt19937 rd(114514);
const int N = 2e5 + 10;
int mvx[4] = {1, -1, 0, 0}, mvy[4] = {0, 0, 1, -1};
int top = -1;
PII stk[N];
int n, h[N];
int ans[N];
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cin >> n;
for (int i = 1; i <= n; i ++) {
std::cin >> h[i];
}
for (int i = 1; i <= n; i ++) {
if (top == -1) {
ans[i] = h[i] * i;
} else {
while (stk[top].first < h[i] && top >= 0) {
top --;
}
ans[i] = h[i] * (i - stk[top].second) + ans[stk[top].second];
}
stk[++ top] = {h[i], i};
}
for (int i = 1; i <= n; i ++) {
std::cout << ans[i] + 1 << " ";
}
return 0;
}