らての精進日記

修行をします

joi春合宿2015 day1-2:En-JOI-able Logo Design

解法

円環の問題なので引き伸ばして2*Nの列にして、適当に累積和取ったら通った。

コード

#include<bits/stdc++.h>
using namespace std;

int K,N;
char str[1<<21];
int S[1<<21];
int sum[3][1<<23];
int main(){
    scanf("%d%s",&K,str);
    int N=1<<(2*K);

    for(int i=0;i<N;i++){
        switch(str[i]){
            case 'J':S[i]=0;break;
            case 'O':S[i]=1;break;
            case 'I':S[i]=2;break;
        }
    }

    for(int i=0;i<N;i++){
        sum[S[i]][i+1]++;
        sum[S[i]][N+i+1]++;
    }

    for(int k=0;k<3;k++){
        for(int i=0;i<2*N;i++){
            sum[k][i+1]+=sum[k][i];
        }
    }

    int mi=1001001001;

    for(int i=0;i<N;i++){
        int prev=i;
        int cost=0;
        for(int j=K-1;j>=0;j--){
            for(int k=0;k<3;k++){
                cost+=(1<<(2*j))-(sum[k][prev+(1<<(2*j))]-sum[k][prev]);
                prev+=(1<<(2*j));
            }
        }
        mi=min(mi,cost);
    }

    printf("%d\n",mi);
    return 0;
}