zoukankan      html  css  js  c++  java
  • 机房测试2:sushi(断环+贪心)

    题目:

     分析:

    因为原序列是一个环,所以要断环为链,将序列复制一份放在后面。

    显然将R移动到一块的同时,B也会在一块,所以只需要求R移动到一起的贡献即可。

    枚举一个分界点,让这个点左边所有的R都向左靠,右边所有的R都向右靠。这时候一定是满足题意的。

    但会发现,同一个分界点,随着断环的位置改变,统计出来的答案也会改变,所以还要枚举一个断环点

    复杂度是n^2

    考虑优化:

    RRBBRBBBR 像这样一组数据,把将R向两边放看做是将B往中间靠,那么在第5个位置是最优的(左边移两格,右边不需要移)。

    当断环的点向右移,lr不会增加,rr不会减少,相当于如果分界点向左移动,只会给右边带来更多的花费,也不会给左边减少花费(因为移动的是最左边的点)。

    所以断环的点不会从原来的位置向左移动。

    显然我们不需要将分界点从头枚举到尾,我们只需要找到一个最大的位置,当答案不再减小,就break掉(也就是说答案随分界点的变化是单调的)。

    复杂度:接近O(n)

    实现流程:

    定义lr为左边R的个数,rr为右边R的个数,r为当前所需花费。枚举断环点,枚举分界点,统计答案。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 1000005
    #define ri register int
    char s[N<<1];
    void work()
    {
        int n=strlen(s+1);
        for(ri i=1;i<=n;++i) s[i+n]=s[i];
        //断点指断环的点 分界点指不移动的点 将所有的B往中间分界点靠 R向两边靠 
        int lr=0,rr=0;
        ll r=0,ans;
        for(ri i=1;i<=n;++i) if(s[i]=='R') r+=n-i-rr,rr++;//预处理断点在1的情况
        //printf("%lld
    ",rr);
        ans=r;
        int now=1;
        for(ri pos=1;pos<=n;++pos){//移动断点 
            while(now<n+pos){//枚举分界点 跳指针移动 
                if(s[now]=='R'){//移动B不影响 移动R会对lr 与 rr的统计有影响 
                    ll tmp=r;
                    rr--;//移到了一个R 所以先右边的-- 减去它自己 便于下面统计 注意分界点这个点是包括在右区间里面的 
                    tmp+=now-pos-lr-(pos+n-1-now-rr);//pos是它目前的起点 pos+n-1是目前的终点 
                    //统计步数:这个R本来有移到右边的贡献 现在减去 加上移到左边的贡献 
                    lr++;//左边的++ 便于上面的统计 
                    if(tmp<=r) r=tmp;//如果不能更新 就还原 然后break 
                    else{ lr--; rr++; break; }
                }
                now++;
            }
            ans=min(ans,r);
            if(s[pos]=='R') lr--,rr++;//如果把R移过去了 右边的R++ 左边-- 
            else r+=rr-lr;//如果移动的是B 就要加上所有右边的R移动到右边的贡献 减去左边的R移动到左边的贡献
        }
        printf("%lld
    ",ans);
    }
    int main()
    {
        freopen("sushi.in","r",stdin);
        freopen("sushi.out","w",stdout);
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%s",s+1);
            work();
        }
    }
    /*
    1
    BBRBBRBBBRRR
    */
  • 相关阅读:
    利用WEBPART部件之间的数据连接功能,筛选知识库
    + 网页制作效果常用代码
    你或许还未听说过的一些ASP.NET 2.0要诀 [转]
    关闭Windows Server 2003关机事件跟踪程序
    Windows SharePoint Services 3.0 应用程序模板中文版(图解)
    零基础学Python不迷茫——基本学习路线及教程!
    小白安装Python环境详细步骤!
    Python入门第一课——Python的起源、发展与前景!
    7款公认比较出色的Python IDE,你值得拥有!
    Windows平台下gitbook的安装与使用
  • 原文地址:https://www.cnblogs.com/mowanying/p/11622618.html
Copyright © 2011-2022 走看看