luogu problem solving P3709 [Uncle's string problem]

  • Topic link:

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

  • Ideas:

First of all, I didn't understand the title. I browsed the dalao in the discussion area and found that it was to find the number of occurrences of the interval mode.

Then we must use Mo team. How to write Mo team and other problem solutions are written in detail, so I won't go into details here. Then the observation data range 1e9 must be discretized.

But there is not much discretization in the solution, so I will talk about a discretization method that I messed around with.

I see that other dalao in the solution are lower_bound or fairy operations that I can't understand. And for konjac, I came up with a more violent and easy-to-understand method---opened two maps.

The first map al is used for discretization, recording whether the element has appeared.

The second map getrk, as the name suggests, is used to discretize to get the rank of each number.

dat[] is used to record the original string , num[] is used to record the number after deduplication , that is, all the elements that appear

After reading the string, sort num[] from large to small, record the ranking of each element that appears, of course, use getrk

Then, regardless of num[], we traverse it to get the rank of each number in the original string to complete the discretization.

Since map is turned on, the constant is relatively large, and it took more than 2000 ms to turn on O2, but it was enough to pass.

  • Code:
// 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;
 } 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325042886&siteId=291194637