zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    文件合并
    排序
    canvas 的cliprect()实现画布剪切DEMO
    SurfaceViewDemo
    View实现事件监听DEMO(文本跟随触屏事件)
    android progressBar和seekBar的小DEMO
    Android DrawerLayoutDemo
    Fragment和FragmentActivity使用Demo
    SharedPreferences DEMO
    android中sharedPreferences的用法
  • 原文地址:https://www.cnblogs.com/newera/p/9363288.html
Copyright © 2011-2022 走看看