题解:P14406 [JOISC 2015] 愉快的标志设计 / En-JOI-able Logo Design
比较小清新的题目。
发现题目给出的序列很明显就是由
不难发现,对于前
但是对于最后一种序列,我们发现和当前处理的序列是属于同一种类型,但是问题规模更小。所以对于最后一种序列我们递归求解就好了。
分析时间:求解前
因为可以从任意起点出发,我们破环成链,预处理前缀和,再枚举起点,总共枚举
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define V vector
#define FOR(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define pb push_back
const int INF=1e9+10;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int k;cin>>k;
string s;cin>>s;
int n=(1<<(2*k));
V<int>num(2*n+1),sumj(2*n+1,0),sumo(2*n+1,0),sumi(2*n+1,0);
FOR(i,1,n) num[i]=num[i+n]=s[i-1];
FOR(i,1,2*n){
sumj[i]=sumj[i-1]+(num[i]=='J');
sumo[i]=sumo[i-1]+(num[i]=='O');
sumi[i]=sumi[i-1]+(num[i]=='I');
}
function<int(int,int)>dfs=[&](int dep,int l){
if(dep==0) return 0;
int l1=l+(1<<(2*(dep-1))),l2=l1+(1<<(2*(dep-1))),l3=l2+(1<<(2*(dep-1)));
int ans1=sumj[l1-1]-sumj[l-1];
int ans2=sumo[l2-1]-sumo[l1-1];
int ans3=sumi[l3-1]-sumi[l2-1];
return l3-l-(ans1+ans2+ans3)+dfs(dep-1,l3);
};
int ans=INF;
FOR(i,1,n){
ans=min(ans,dfs(k,i));
}
cout<<ans;
return 0;
}