• NOIP 模拟 7 寿司


    题解

    题目

    这道题考试的时候直接打暴力,结果暴力连样例都过不了,最后放上去一个玄学东西,骗了 (5pts)

    正解:

    此题中我们可以看到原序列是一个环,所以我们要把它拆成一条链,那么我们需要暴力枚举每个点作为断点,这里没有什么好的优化,因为没什么特殊性质

    对于每个字符,其对答案的贡献为 (sum_i^nmin(l_i,r_i)) ,其中 (l_i)(r_i) 为点 (i) 向左或向右移动到边界的步数,通过手模我们可以发现这就是点 (i)最左最右经过的另一种颜色的个数

    所以此时我们能容忍的复杂度上只能再加一个 (mathcal O(log)) 或者 (mathcal O(1)),对于 (mathcal O(log)) 我么考虑二分,但我没看出来哪里能二分,所以我去考虑 (mathcal O(1)),对于 (mathcal O(1)) 我们可以发现在学单调性时有这东西

    所以我们考虑维护一个单调指针,对于断点顺时针移动,我们设一个分界点,分界点左侧的向左移动到做边界,右边的同理,那么我们可以发现,最有分解点就是没有一个最有交换经过它,因此这个分解点也是单调顺时针移动的。

    复杂度分析,对于一个环,我们把它变成一条链,那么它的长度为 (2n-1) 而指针单调移动不会出这个范围,所以此复杂度为 (mathcal O(n))

    目前为止,本篇题解是时间最优的一篇,空间也最小,(1.3s)(17mb) (不开 (mathcal O(2)) )。

    (ACkern 0.4emCODE:)

    Code
    #include<bits/stdc++.h>
    #define ri register int
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        inline int read() {
            ri x=0,f=1;char ch=getchar();
            while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
            return x*f; 
        }
    }
    using IO::read;
    namespace nanfeng{
        #define int long long
        #define cmax(x,y) ((x)>(y)?(x):(y))
        #define cmin(x,y) ((x)>(y)?(y):(x))//常数优化
        #define FI FILE *IN
        #define FO FILE *OUT
        static const int N=2e6+7;
        int l[N],bac[N],T,ans,tl;
        char col[N];
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            T=read();
            for (ri z(1);z<=T;p(z)) {
                scanf("%s",col+1);//读入优化
                int B=0,R=0,lc=0,cnt=0,mv=0,la=0,tp=0,num=0,tot,tt,tmp=0;
                int len=strlen(col+1);
                for (ri i(1);i<=len;p(i)) {if (col[i]=='B') p(B);else p(R);} 
                char pc=B<R?'B':'R';//移动数量少的颜色,卡常
                tt=cmin(B,R);tot=B+R-tt;
                for (ri i(1);i<=len;p(i)) {
                    if (col[i]==pc) l[p(tp)]=cnt,bac[i]=tp;
                    else p(cnt);
                }
                num=tp;tl=1;
                while(l[tl]<tot-l[tl]) tmp+=l[tl],p(tl),p(la);
                for (ri i(tl);i<=tt;p(i)) tmp+=tot-l[i];
                ans=tmp;
                if (col[1]!=pc) p(mv),tmp+=(tt-la)-la;
                else --la,l[tp+1]=l[1]+tot,p(num);
                for (ri i(2);i<=len;p(i)) {
                    int k;
                    while((k=(l[tl]-mv))<tot-k&&tl<=num) tmp+=k-(tot-k),p(tl),p(la); 
                    ans=cmin(ans,tmp);
                    if (col[i]==pc) {--la;l[tp+bac[i]]=l[bac[i]]+tot;p(num);continue;}//记得在换点时建立新的点数据
                    else p(mv),tmp+=(tt-la)-la;
                }
                printf("%lld
    ",ans);
            }
            return 0;
        }
        #undef int
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    2017 年终总结 —— 在路上
    尝试造了个工具类库,名为 Diana
    走近 Python (类比 JS)
    Node.js 异步异闻录
    使用 Node.js 搭建一个 API 网关
    不就是语法和长难句吗—笔记总结Day4
    不就是语法和长难句吗—笔记总结Day3
    不就是语法和长难句吗—笔记总结Day2
    不就是语法和长难句吗—笔记总结Day1
    Kali Day1
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/14876503.html
Copyright © 2020-2023  润新知