UPC Game Night 思维

问题 G: Game Night

时间限制: 1 Sec  内存限制: 128 MB
提交: 42  解决: 16
[提交] [状态] [命题人:admin]

题目描述

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 how well he knows them: the Acquaintances on team A, the Buddies on team B, and the Colleagues on team C.
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?

 

输入

• The first line of the input contains the integer n, where 1 ≤ n ≤ 105 is the number of players (as well as seats).
• The second line contains a string of length n, consisting only of the characters in ABC.
This indicates the teams of the people sitting around the table in order.

 

输出

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

 

样例输入

复制样例数据

5
ABABC

样例输出

2

 

[提交][状态]

题意:一共只有三种字母ABC,围成环形,要使三种字母相同的聚在一起,需要最少多少个字母需要换位置

思路:逆向思维,求不需要换位置的字母个数

将每个字母出现的位置分别压到vector中,排序,每次二分求,具体代码里解释

代码:

#include <bits/stdc++.h>

using namespace std;
string s;
int cnt[5];
vector<int> p[5];

int cal(int i, int x) { // 计算数组从i到位置x,有多少个相应字母,即不需要换座位的
    int l = 0, r = p[i].size();
    while (l < r) {
        int mid = (l + r) >> 1;
        if (p[i][mid] < x) l = mid + 1;
        else r = mid;
    }
    return l;
}

int main() {
    int n;
    scanf("%d", &n);
    cin >> s;
    for (int i = 0; i < n; i++) {
        cnt[s[i] - 'A']++;
        p[s[i] - 'A'].push_back(i);
        p[s[i] - 'A'].push_back(i + n);
    }
    sort(p[0].begin(), p[0].end());
    sort(p[1].begin(), p[1].end());
    sort(p[2].begin(), p[2].end());
    int ans = 0; //ans表示有多少字母不需要换
    for (int i = 0; i < n; i++) {
        ans = max(ans, cal(0, cnt[0] + i) - cal(0, i) + cal(1, cnt[0] + cnt[1] + i) - cal(1, cnt[0] + i) +
                       cal(2, cnt[0] + cnt[1] + cnt[2] + i) - cal(2, cnt[0] + cnt[1] + i));
        ans = max(ans, cal(0, cnt[0] + i) - cal(0, i) + cal(2, cnt[0] + cnt[2] + i) - cal(2, cnt[0] + i) +
                       cal(1, cnt[0] + cnt[1] + cnt[2] + i) - cal(1, cnt[0] + cnt[2] + i));
    }
    printf("%d\n", n - ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值