1. 程式人生 > >luogu題解 P3709 【大爺的字符串題】

luogu題解 P3709 【大爺的字符串題】

出現 出了 數組長度 其他 == pre har return 出現次數

  • 題目鏈接:

https://www.luogu.org/problemnew/show/P3709

  • 思路:

首先我是沒讀懂題目的,瀏覽了討論區的dalao發現才知道就是求區間眾數的出現次數。

然後肯定是用莫隊,具體怎麽寫莫隊其他題解都寫得很詳細,這裏不贅述.然後觀察數據範圍1e9肯定要離散化。

但是題解裏講離散化的不多,我就講一講我自己瞎搞的一個離散化方法

看到題解裏其他dalao都是什麽lower_bound或我看不懂的神仙操作。而蒟蒻我就瞎搞出了一個比較暴力的,也通俗易懂方法---開了兩個map.

第一個map al用來離散化,記錄元素是否出現過.

第二個map getrk顧名思義,用來離散化獲取每個數的排名.

dat[]用來記錄原字符串,num[]用來記錄去重後的數,即所有出現的元素

讀入字符串後將num[]從大到小排序,記錄每一個出現元素的排名,當然就是用getrk

接著就不管num[],我們遍歷一遍獲取原字符串中每個數的排名完成離散化.

由於開了map,常數比較大,開了O2跑了2000多ms,但是能過就行了

  • 代碼:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <map>
#include <cmath>
using namespace std;
const int maxn=200005;
map <int,bool>al;
map <int,int>getrk;
struct Ask{
    int l,r,id,x;
}ask[maxn];
int num[maxn],dat[maxn],rk[maxn];
int belong[maxn],block;
int N,n=0,m;
int a[maxn],cnt[maxn];
int ans[maxn],anss=0;
template<class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;
    return ;
}
inline bool cmp0(const int&x,const int&y){
    return x>y;
}
inline bool cmp2(const Ask &x,const Ask &y){
    return belong[x.l]^belong[y.l]?belong[x.l]<belong[y.l]:belong[x.l]&1?x.r<y.r:x.r>y.r;
}
inline void init()
{
    int x;
    read(N),read(m);
    block=N/sqrt(m*2/3);
    n=0;
    for(register int i=1;i<=N;i++){//N是原字符串長度
        read(x);
        dat[i]=x;
        if(al[x]==0){//去重
          num[++n]=x;//n是去重後num[]數組長度
          al[x]=1;
         } 
        belong[i]=(i-1)/block+1;
    }
    sort(num+1,num+1+n,cmp0);
    for(register int i=1;i<=n;i++){
        getrk[num[i]]=i;
  //      belong[i]=(i-1)/block+1;
    }
    for(register int i=1;i<=N;i++){
        rk[i]=getrk[dat[i]];
    }
    //sort(num+1,num+1+n,cmp1);
    for(register int i=1;i<=m;i++){
        read(ask[i].l),read(ask[i].r);
        ask[i].id=i;
    }
    sort(ask+1,ask+1+m,cmp2);
    return;
}
inline void add(int x){
    int now=rk[x];
    if(anss==a[now])anss++;
    cnt[a[now]]--;
    a[now]++;
    cnt[a[now]]++;
    return;
} 
inline void sub(int x){
    int now=rk[x];
    if(anss==a[now]&&cnt[a[now]]==1)anss--;
    cnt[a[now]]--;
    a[now]--;
    cnt[a[now]]++;
    return;
}
inline void solve()
{
    int l=1,r=0,ll,rr;
    cnt[0]=n;
    for(register int i=1;i<=m;i++){
        ll=ask[i].l,rr=ask[i].r;
        while(r<rr)add(++r);
        while(r>rr)sub(r),r--;
        while(l<ll)sub(l),l++;
        while(l>ll)add(--l); 
        ans[ask[i].id]=anss;
    }
    for(register int i=1;i<=m;i++){
        printf("-%d\n",ans[i]);
    }
    return ;
}
int main()
{
    init();
    solve();
    return 0;
 } 

luogu題解 P3709 【大爺的字符串題】