专栏文章
题解:P14406 [JOISC 2015] 愉快的标志设计 / En-JOI-able Logo Design
P14406题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min2zgy6
- 此快照首次捕获于
- 2025/12/01 19:43 3 个月前
- 此快照最后确认于
- 2025/12/01 19:43 3 个月前
头一次见把解题过程写在题面里的题目。
思路
破环为链后倍长,考虑对于每个位置作为开头进行计算。
然后你发现对于一个 ,你直接预处理
J、O、I 的前缀出现次数,就能够把一个 级序列归约到一个 级别序列的问题上。设 表示从第 个位置开始构成一个 级别的序列所需要的最小代价,递推是显然的,可以从 直接推得。
然后你发现 ,这题就做完了。
真是何意味,时间复杂度 ,瓶颈在于读懂题目。
代码
代码
CPP#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll int
using namespace std;
const ll N=(1<<21)+10;
const ll INF=2147483647;
ll k,f[N][11],suma[N],sumb[N],sumc[N];
string s;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>k>>s;s=' '+s+s;
ll n=(1<<(2*k));
for(ll i=1;i<=2*n;i++){
f[i][0]=0;
suma[i]=suma[i-1]+(s[i]=='J');
sumb[i]=sumb[i-1]+(s[i]=='O');
sumc[i]=sumc[i-1]+(s[i]=='I');
}
for(ll i=2*n;i;i--){
for(ll j=1;j<=k;j++){
if(i+(1<<(j*2))-1>2*n) break;
f[i][j]=f[i+3*(1<<((j-1)*2))][j-1];
f[i][j]+=(1<<(2*(j-1)))-suma[i+(1<<(2*(j-1)))-1]+suma[i-1];
f[i][j]+=(1<<(2*(j-1)))-sumb[i+2*(1<<(2*(j-1)))-1]+sumb[i+(1<<(2*(j-1)))-1];
f[i][j]+=(1<<(2*(j-1)))-sumc[i+3*(1<<(2*(j-1)))-1]+sumc[i+2*(1<<(2*(j-1)))-1];
}
}
ll ans=INF;
for(ll i=1;i<=n;i++) ans=min(ans,f[i][k]);
cout<<ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...