历年 CSP / NOIP 补题记录
P9753 [CSP-S 2023] 消消乐
AC on 2025.11.17
当年考场上只打出了最无脑的区间dp,导致 135pts 连一等奖都拿不到
所以打暴力应该也要先想优化再打呀,不要有一个很劣的想法就直接去打了
(真的很重要,CSP-S 2025 T3 也是一样的问题呀,最后只拿了 5pts 却花了 1h,假如能先想一下,说不定时间花的更少拿的分却更高,不过可能还是实力没到吧)
暴力优化:\(O(n^2)\) 的想法也很简单,固定左端点再遍历
正解:很显然 \(n^2\) 的算法重复算了哪些要被消掉,所以可以用 \(lst_i\) 记录最远能消除到哪, \(dp_i\) 记录能消几个
但是同种思路不同写法差异也会很大诶,我自己写得要记录一堆东西维护,可是别人理清思路写的很简便
所以想到一种写法后先不要着急打呀,先用样例模拟一遍再想想有什么 corner case 再想想怎么打更简单一点呢
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6+5;
int n, lst[N], dp[N];
ll ans;
string s;
int main(){
cin >> n;
cin >> s;
s = ' ' + s;
for(int i=2;i<=n;i++){
for(int j=i-1;j>=1;j=lst[j]-1){
if(s[i] == s[j]){
dp[i] = dp[j-1]+1;
lst[i] = j;
ans += dp[i];
break;
}
}
}
cout << ans;
return 0;
}
\(\,\)
P1600 [NOIP 2016 提高组] 天天爱跑步
AC on 2025.11.26
也是很久以前就看过的题了,当时看题解都没懂,诶
将一条路径拆分为向上的路径和向下的路径,然后再做树上差分
最重要的其实是统计,进入一个节点后要先记录一下值 \(val\),出节点的时候再减去 \(val\),这样就防止了其他路径对这个节点的影响了

浙公网安备 33010602011771号