• [P3709] 大爷的字符串题


    Link:

    P3709 传送门

    Solution:

    lxl出的语文题

    其实转化一下就是求将当前区间最少拆分成多少个严格单调上升序列(可不连续)

    再转化一下就是求区间内的众数个数

    本来求众数的套路是主席树+二分

    但此题不要求在线,用莫队同时维护$i$的出现次数$cnt[i]$和出现次数为$i$的数的个数$sum[i]$

    这样在删除时仅当$sum[cnt[dat[pos]]]==1$时才减少$cur$

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=5e5+10;
    struct Query{int l,r,id;}qry[MAXN];
    int n,m,cnt[MAXN],sum[MAXN],res[MAXN],dat[MAXN],dsp[MAXN],tot,blk,cur;
    
    int cal(int x){return (x-1)/blk+1;}
    bool cmp(Query x,Query y)
    {return cal(x.l)==cal(y.l)?x.r<y.r:x.l<y.l;}
    
    void upd(int pos,int val)
    {
        int &k=cnt[dat[pos]];
        if(val==1&&cur==k) cur++;
        else if(val==-1&&cur==k&&sum[cur]==1) cur--;
        sum[k]--;sum[k+val]++;k+=val;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);blk=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            scanf("%d",&dat[i]),dsp[i]=dat[i];
        sort(dsp+1,dsp+n+1);tot=unique(dsp+1,dsp+n+1)-dsp-1;
        for(int i=1;i<=n;i++)
            dat[i]=lower_bound(dsp+1,dsp+tot+1,dat[i])-dsp;
        for(int i=1;i<=m;i++)
            scanf("%d%d",&qry[i].l,&qry[i].r),qry[i].id=i;
        
        sort(qry+1,qry+m+1,cmp);
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
            while(l>qry[i].l) upd(--l,1);
            while(r<qry[i].r) upd(++r,1);
            while(l<qry[i].l) upd(l++,-1);
            while(r>qry[i].r) upd(r--,-1);
            res[qry[i].id]=-cur;
        }
        for(int i=1;i<=m;i++) printf("%d
    ",res[i]);
        return 0;
    }
  • 相关阅读:
    注意:MagickReadImageBlob() 引发的问题
    Notepad++ 【自动完成】与【输入时提示函数参数】互相冲突,无奈
    收藏:png8和png24的根本区别
    【物理分辨率】与【逻辑分辨率】
    算法
    算法
    Linux 用户和文件
    Oracle索引技术研究
    Linux Socket
    Linux Socket
  • 原文地址:https://www.cnblogs.com/newera/p/9363288.html
Copyright © 2020-2023  润新知