• 【洛谷3709】大爷的字符串题(离散化+莫队)


    点此看题面

    大致题意: 算法标签——语文,给定一个数列,多组询问,每次询问一个区间内的众数出现的次数。

    莫队

    这道题的算法应该是莫队

    如何用莫队求解此题

    我们可以用(cnt)数组记录下每个数出现的次数(注意要先离散化),用(tot)数组记录下每个数在(cnt)数组中的出现次数,并用(ans)记录答案。

    当我们要加入一个新数(x)的时候,如果加入前的(cnt_x=ans),则加入后的(cnt_x)肯定大于(ans),因此将(ans)(1)

    当我们要删除一个数(x)的时候,如果删除前(cnt_x=ans)(tot_{ans}=1),则删除该元素后就没有元素的出现个数为(ans)了,因此将(ans)(1)

    这样就可以了。

    代码

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define abs(x) ((x)<0?-(x):(x))
    #define LL long long
    #define ull unsigned long long
    #define swap(x,y) (x^=y,y^=x,x^=y)
    #define Fsize 100000
    #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
    #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,Fsize,stdout),Fout[(FoutSize=0)++]=ch))
    #define N 200000
    int FoutSize=0,OutputTop=0;char Fin[Fsize],*FinNow=Fin,*FinEnd=Fin,Fout[Fsize],OutputStack[Fsize];
    using namespace std;
    int n,Q,blo,s,a[N+5],p[N+5],bl[N+5],cnt[N+5],tot[N+5],res[N+5];
    struct Query
    {
        int l,r,pos;
    }q[N+5];
    inline void read(int &x)
    {
        x=0;static char ch;
        while(!isdigit(ch=tc()));
        while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
    }
    inline void write(int x)
    {
        if(!x) return (void)pc('0');
        while(x) OutputStack[++OutputTop]=x%10+48,x/=10;
        while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;
    }
    inline bool cmp(Query x,Query y)//将询问排序
    {
        return bl[x.l]^bl[y.l]?bl[x.l]<bl[y.l]:(bl[x.l]&1?x.r<y.r:x.r>y.r);
    }
    inline int find(int x)//求出离散化后的值
    {
        register int l=1,r=s,mid;
        while(l<=r) p[mid=l+r>>1]<x?l=mid+1:r=mid-1;//二分查找
        return l;
    }
    int main()
    {
        register int i;
        for(read(n),read(Q),blo=sqrt(n),i=1;i<=n;++i) read(a[i]),p[i]=a[i],bl[i]=(i-1)/blo+1;
        for(sort(p+1,p+n+1),s=unique(p+1,p+n+1)-p-1,i=1;i<=n;++i) a[i]=find(a[i]);//将原数组离散化
        for(i=1;i<=Q;++i) read(q[q[i].pos=i].l),read(q[i].r);
        register int L=1,R=1,ans=tot[1]=1;
        for(sort(q+1,q+Q+1,cmp),cnt[a[1]]=i=1;i<=Q;++i)//以下为莫队的主要过程
        {
            while(R<q[i].r) {++R,--tot[cnt[a[R]]],++tot[++cnt[a[R]]];if(cnt[a[R]]>ans) ++ans;}//将区间右边界增加
            while(L>q[i].l) {--L,--tot[cnt[a[L]]],++tot[++cnt[a[L]]];if(cnt[a[L]]>ans) ++ans;}//将区间的左边界减小
            while(R>q[i].r) {if(!--tot[cnt[a[R]]]&&!(cnt[a[R]]^ans)) --ans;++tot[--cnt[a[R--]]];}//将区间的右边界减小
            while(L<q[i].l) {if(!--tot[cnt[a[L]]]&&!(cnt[a[L]]^ans)) --ans;++tot[--cnt[a[L++]]];}//将区间的左边界增大
            res[q[i].pos]=ans;//用res[]数组存储答案
        }
        for(i=1;i<=Q;++i) (res?pc('-'):0),write(res[i]),pc('
    ');//按读入的顺序输出答案
        return fwrite(Fout,1,FoutSize,stdout),0;
    }
    
  • 相关阅读:
    css 边框添加四个角效果
    PS 怎么去掉噪点
    Packet Tracer——添加温度计
    zabbix监控mysql数据
    日常检测
    mysql的基本命令操作
    判断字典中是否有这个单词
    批量创建用户
    检测局域网ip存活状态
    spring boot gradle build:bootRepackage failed
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3709.html
Copyright © 2020-2023  润新知