[P3709] 大爷的字符串题

Posted newera

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[P3709] 大爷的字符串题相关的知识,希望对你有一定的参考价值。

Link:

P3709 传送门

Solution:

lxl出的语文题

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

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

 

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

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

这样常规套路更新结果就好了

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;
}

 

以上是关于[P3709] 大爷的字符串题的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3709大爷的字符串题

P3709 大爷的字符串题(50分)

洛谷 P3709 大爷的字符串题

luogu题解 P3709 大爷的字符串题

LuoguP3709 大爷的字符串题

大爷的字符串题 莫队