G - Game Night (前缀和)

It is finally Bobby’s birthday, and all of his Acquaintances, Buddies and Colleagues have gathered for a board game night. They are going to play a board game which is played in up to three big teams. Bobby decided to split his guests into groups based on how well he knows them: the Acquaintances on team AA, the Buddies on team BB, and the Colleagues on team CC.

While Bobby was busy explaining the rules to everyone, all his guests already took seats around his large, circular living room table. However, for the game it is crucial that all people sitting on a team are sitting next to each other. Otherwise, members of other teams could easily eavesdrop on their planning, ruining the game. So some people may need to change seats to avoid this from happening.

Bobby wants to start playing the game as soon as possible, so he wants people to switch seats as efficiently as possible. Given the current arrangement around the circular table, can you figure out the minimal number of people that must switch seats so that the teams are lined up correctly?

Input

  • The first line of the input contains the integer nn, where 1≤n≤1051≤n≤105 is the number of players (as well as seats).

  • The second line contains a string of length nn, consisting only of the characters in ABC. This indicates the teams of the people sitting around the table in order.

Output

Print a single integer: the minimal number of people you have to ask to move seats to make sure the teams sit together.

Sample Input 1Sample Output 1
5
ABABC
2
Sample Input 2Sample Output 2
12
ABCABCABCABC
6
Sample Input 3Sample Output 3
4
ACBA
0
Sample Input 4Sample Output 4
6
BABABA
2
Sample Input 5Sample Output 5
9
ABABCBCAC

题意:给你一条长度n的字符串,代表n个人坐在一个圆桌上(坐满), 每个人都在a,b,c三个组中,每次个调换两个人的位置,问:最小需要调换多少人能达到最少操作次数使这三组中的人都相邻

思路:暴力走n,预处理一个2*n的前缀和,for循环遍历n,选取a的位置(一个区间),再分别确定b,c的位置,取三组区间的最大数量之和,再用n减去

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const ll inf =1e9*10;
int a,b,c;
int n;
int sum[4][maxn*2];
int getdelete(int l)
{
    int pos=0;
    int res=0;
//    cout<<sum[1][l+a-1]-sum[1][l-1]<<" "<<sum[2][l+a+b-1]-sum[2][l+a-1]<<" "<<sum[3][l+a+b+c-1]-sum[3][l+a+b-1]<<endl;
    pos+=sum[1][l+a-1]-sum[1][l-1]+sum[2][l+a+b-1]-sum[2][l+a-1]+sum[3][l+a+b+c-1]-sum[3][l+a+b-1];
    res+=sum[1][l+a-1]-sum[1][l-1]+sum[3][l+a+c-1]-sum[3][l+a-1]+sum[2][l+a+b+c-1]-sum[2][l+a+c-1];
//    cout<<pos<<" "<<res<<endl;
    return min(n-pos,n-res);
}
int main()
{
    cin>>n;
    string s;
    cin>>s;
    for(int i=0;i<2*n;i++)
    {
        sum[1][i+1]=sum[1][i];
        sum[2][i+1]=sum[2][i];
        sum[3][i+1]=sum[3][i];
        int x=i;
        if(x>=n) x%=n;
        if(s[x]=='A') sum[1][i+1]++,a++;
        else if(s[x]=='B') sum[2][i+1]++,b++;
        else if(s[x]=='C') sum[3][i+1]++,c++;
//        cout<<sum[1][i+1]<<" ";
    }
    a/=2;
    b/=2;
    c/=2;
//    cout<<endl;
    int ans=n+1;
    for(int i=1;i<=n;i++)
    {
        ans=min(ans,getdelete(i));
    }
    cout<<ans<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值