Codeforces 1268B
贪心的思想,从右往左把每列都取完或剩下一个(取余2)。
观察画图可以发现,若剩下一个的两列之间间隔列数为偶数的话,是可以通过最底下一行使得这两列剩下的那一个合并使得贡献加1。
#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int maxn=3e5+5;
stack <int> s;
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int n;cin>>n;
ll ans=0;
for(int i=1;i<=n;i++){
int t;cin>>t;
ans+=t/2;
t%=2;
if(!t) continue;
if(!s.size()||s.top()==i%2) s.push(i%2);
else{
ans++;
s.pop();
}
}
cout<<ans<<endl;
}
Codeforces 1132F
一眼区间DP。
dp[i][j]表示合并i至j使得只剩下一个s[j]需要的最少次数,转移方程显而易见:
若s[k]与s[j]相同,那么合并时不需要多余的贡献,否则应该+1;
#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int maxn=505;
const int inf=0x3f3f3f3f;
int dp[maxn][maxn];
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int n;cin>>n;
string s;cin>>s;
memset(dp,inf,sizeof(dp));
for(int i=0;i<n;i++) dp[i][i]=0;
for(int len=1;len<=n;len++){
for(int i=0;i<n;i++){
int j=len+i-1;
if(j>=n) continue;
for(