• 12.25模拟赛T1


    可以区间dp,但是复杂度太高。

    所以应该是贪心,怎么贪心呢?

    这种题目,最好还是手玩找一些规律。

    可以发现,由于保证可以m次填完,所以颜色之间没有相互包含关系。

    比较像分治的模型。

    所以考虑拿到一个区间怎么处理。

    假设a[l]==a[r],那么为了合法,一定先刷这种颜色。然后分部分递归下去。

    否则,对于区间:AEEGEABBBCDDC

    里面的夹心肯定不能先处理了,可以大概看做:A..AB..BC..C

    先刷哪一个?

    刷两边长度较小的一个

    证明:

    如果刷中间,那么中间的位置之后就不能再动了。如果刷比较长的一个,那么之后不能再动。

    如果刷比较短的一个,长的可以再多刷几次,贡献更大。

    比较即可。(如果两边长度相同,比较下一个。)

    O(m^2+n)

    理论上可以后缀数组优化到:O(mlogn+n)

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1e5;
    const int M=5005;
    int st[M],nd[M];
    ll ans;
    int a[N];
    int n,m;
    vector<int>mem[M];
    void sol(int l,int r){
        //cout<<" sol "<<l<<" "<<r<<" "<<ans<<endl;
        if(l>r) return;
        if(l==r){
            ++ans;return;
        }
        if(a[l]==a[r]){
            ans+=r-l+1;
            int las=l;
            for(reg i=1;i<mem[a[l]].size();++i){
                sol(las+1,mem[a[l]][i]-1);
                las=mem[a[l]][i];
            }
        }
        else{
            int L=l,R=r;
            int go=0;
            ans+=r-l+1;
            while(!go){
                if(nd[a[L]]-st[a[L]]+1<nd[a[R]]-st[a[R]]+1){
                    go=l;break;
                }else if(nd[a[L]]-st[a[L]]+1>nd[a[R]]-st[a[R]]+1){
                    go=r;break;    
                }
                L=nd[a[L]]+1;R=st[a[R]]-1;
                if(L>R) go=l;
            }
            if(go==l){
                int las=l;
                for(reg i=1;i<mem[a[l]].size();++i){
                    sol(las+1,mem[a[l]][i]-1);
                    las=mem[a[l]][i];
                }
                sol(las+1,r);
            }else{
                int las=st[a[r]];
                for(reg i=1;i<mem[a[r]].size();++i){
                    sol(las+1,mem[a[r]][i]-1);
                    las=mem[a[r]][i];
                }
                sol(l,st[a[r]]-1);
            }
        }
    }
    int main(){
        rd(n);rd(m);
        for(reg i=1;i<=n;++i){
            rd(a[i]);
            if(st[a[i]]==0) st[a[i]]=i;
            nd[a[i]]=i;
            mem[a[i]].push_back(i);
        }
        sol(1,n);
        printf("%lld",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/25 15:04:11
    */

    总结:

    没有想到的原因是,还是没有从手玩找规律这个方向入手。

    对于一些没有什么思路的题,可以尝试“不完全归纳”

    其实规律还是比较简单的。

  • 相关阅读:
    Python pandas检查数据中是否有NaN的几种方法
    实现one hot encode独热编码的两种方法
    深度学习框架-caffe安装-环境[Mac OSX 10.12]
    Git使用记录
    求解大于某数的下一个素数
    caffe cifar10试跑问题总结
    深度学习框架-caffe安装-Mac OSX 10.12
    常用bash命令
    vim文本编辑器
    第十八周助教总结
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10175755.html
Copyright © 2020-2023  润新知