寿司 (拆环为链 大模拟)

来源:互联网 发布:网络优化工程师考试 编辑:程序博客网 时间:2024/05/17 04:03

10.28

这里写图片描述

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

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define LL long long#define N 1000010using 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;    }}
原创粉丝点击