【Luogu】P3709大爷的字符串题(莫队算法)

  题目链接

  语文题啊……

  看题解发现是让求区间中最多的数的个数,于是果断理解了一会题解……莫队套上完事。

  sum[i]表示i这个数出现的次数,cnt[i]表示出现i次的数有几个,然后乱搞搞……就好了

  

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
#define maxn 300000
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int s[maxn];
int q[maxn];
int d[maxn];
int ans[maxn];
struct Que{
    int x,y,id;
    bool operator <(const Que a)const{
        if(s[x]!=s[a.x])    return s[x]<s[a.x];
        return y<a.y;
    }
}que[maxn];

int sum[maxn],cnt[maxn];

int main(){
    int n=read(),m=read();
    int sqt=sqrt(n);
    for(int i=1;i<=n;++i){
        q[i]=d[i]=read();
        s[i]=(i-1)/sqt+1;
    }
    sort(q+1,q+n+1);
    int size=unique(q+1,q+n+1)-q-1;
    for(int i=1;i<=n;++i)    d[i]=lower_bound(q+1,q+size+1,d[i])-q;
    for(int i=1;i<=m;++i)    que[i]=(Que){read(),read(),i};
    sort(que+1,que+m+1);
    int l=0,r=0,now=1;cnt[0]=1;
    for(int i=1;i<=m;++i){
        int x=que[i].x,y=que[i].y;
        while(r<y){
            r++;
            int &o=sum[d[r]];
            if(now==o)    now++;
            cnt[o]--;    o++;    cnt[o]++;
        }
        while(r>y){
            int &o=sum[d[r]];
            cnt[o]--;    if(now==o&&cnt[o]==0)    now--;
            o--;    cnt[o]++;
            r--;
        }
        while(l<x){
            int &o=sum[d[l]];
            cnt[o]--;    if(now==o&&cnt[o]==0)    now--;
            o--;    cnt[o]++;
            l++;
        }
        while(l>x){
            l--;
            int &o=sum[d[l]];
            cnt[o]--;    if(now==o)    now++;
            o++;    cnt[o]++;
        }
        
        ans[que[i].id]=now;
    }
    for(int i=1;i<=n;++i)    printf("%d\n",-ans[i]);
    return 0;
}

 

posted @ 2018-01-19 21:15  Konoset  阅读(145)  评论(0编辑  收藏  举报