寿司 (拆环为链 大模拟)

本文介绍了一种模拟策略,针对特定问题(如寿司排列),通过枚举向哪个点靠拢来解决。讨论了只考虑一种颜色的情况,并解释了如何将环形结构拆解为链状进行递推操作。关键在于理解如何处理环到链的转换并进行倍增处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

10.28

这里写图片描述

思路:
模拟题,枚举向那个点靠拢。
显然只用考虑一种颜色算就好了。
每次向i号点靠拢,前一部分的点靠前,后一部分的点靠后。
然后模拟递推就好了。
这种拆环为链的题一般都要扩倍。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
#define N 1000010
using namespace std;

int len;
char s[N];
int a[N], cnt, num;
LL sum, pos, ans = (1LL << 61);

int main(){
    freopen ("sushi.in", "r", stdin);
    freopen ("sushi.out", "w", stdout);
    int T; scanf("%d", &T);
    while ( T-- ){
        ans = (1LL << 61);
        cnt = num = sum = 0;
        scanf("%s", s+1);
        len = strlen ( s+1 );
        for(register int i=1; i<=len; i++){
            a[i+len] = a[i] = (s[i] == 'R');
            if(a[i] == 0) cnt++;//一共有多少个 
        }
        int id = 0, flag = 0, idd; pos = len + 1;
        for(register int i=1; i<=len; i++){
            if(a[i] == 0){
                if(flag == 1){
                    sum += len - (cnt - ++idd) - i;
                    continue;
                }
                id++;//第一个往后走的是第几个  
                if(i - id > len - (cnt - id) - i){
                    sum += len - (cnt - id) - i;
                    pos = i;//第一个往后走的pos
                    flag = 1; idd = id;//是第几个
                }
                else
                    sum += i - id, num++;//有num个向前
            }
        }
        ans = min(ans, sum);
        for(register int i=2; i<=len; i++){
            if(a[i-1] == 1) sum -= num, sum += cnt - num;
            if(a[i-1] == 0) {
                num--; id--; 
            }
            if(pos <= 2*len)//扩倍 
            for(register int j=pos; j<=2*len; j++){//
                if(a[j] == 0){
                    if((j - i + 1) - id > len - (cnt - id) - (j - i + 1)) break;
                    else {
                        sum -= len - (cnt - id) - (j - i + 1);
                        sum += (j - i + 1) - id, num++, pos = j + 1, id++;
                    }
                }
            }
            ans = min(ans, sum);
        }
        cout << ans << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值