【题解】LuoGu3709:大爷的字符串题

版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/82560919

原题传送门
题目描述
给你一个字符串a,每次询问一段区间的贡献
贡献定义:
每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S
如果S为空,你rp减1
如果S中有一个元素不小于x,则你rp减1,清空S
之后将x插入S
由于你是大爷,平时做过的题考试都会考到,所以每次询问你搞完这段区间的字符之后最多还有多少rp?rp初始为0
询问之间不互相影响~
输入输出格式
输入格式:
第一行两个数n,m,表示字符串长度与询问次数
之后一行n个数,表示字符串
由于你是大爷,所以字符集1e9
之后m行每行两个数,表示询问的左右区间
输出格式:
m行,每行一个数表示答案
输入样例
3 3
3 3 3
3 3
3 3
3 3
输出样例
-1
-1
-1

【题解】
题意:求一段区间内众数的出现次数
用上了刚学的莫队,模板不变,update改一下就好了

Code:

/*
cnt[i]表示数字i出现次数
tot[i]表示出现次数为i的数字的个数
发现本题要开桶,但范围是1e9,所以就愉快地离散化一下
a为初始数组,b为离散后的数组,q为询问数组,print为输出数组
*/
#include <bits/stdc++.h>
#define res register int
#define maxn 200010
using namespace std;
int n,m,ans;
int b[maxn],tot[maxn],cnt[maxn],print[maxn];
struct node1{
    int x,id;
};
node1 a[maxn];
struct node2{
    int l,r,id,pos;
};
node2 q[maxn];

inline bool cmp1(node1 x, node1 y){ return x.x < y.x; }
inline bool cmp2(node2 x, node2 y){ return x.pos == y.pos ? (x.pos & 1 == 0 ? x.r < y.r : x.r > y.r) : x.pos < y.pos; }
inline void update(int x, int y){
    if (tot[cnt[b[x]]] == 1 && y == -1 && ans == cnt[b[x]]) --ans;
    --tot[cnt[b[x]]];
    cnt[b[x]] += y;
    ++tot[cnt[b[x]]];
    ans = max(ans, cnt[b[x]]);
}

int main(){
    scanf("%d%d",&n,&m);
    for (res i = 1; i <= n; ++i){
        scanf("%d",&a[i].x);
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n, cmp1);
    a[0].x = a[1].x - 1; int p = 0;
    for (res i = 1; i <= n; ++i){
        if (a[i].x != a[i-1].x) ++p;
        b[a[i].id] = p;
    }
    int block = int(sqrt(n));
    for (res i = 1; i <= m; ++i){
        scanf("%d%d",&q[i].l, &q[i].r);
        q[i].id = i, q[i].pos = q[i].l / block;
    }
    sort(q + 1, q + 1 + m, cmp2);
    int l = 1, r = 1;
    update(1,1);
    for (res i = 1; i <= m; ++i){
        for (; r < q[i].r; ++r) update(r + 1, 1);
        for (; r > q[i].r; --r) update(r, -1);
        for (; l < q[i].l; ++l) update(l, -1);
        for (; l > q[i].l; --l) update(l - 1, 1);
        print[q[i].id] = -ans;
    }
    for (res i = 1; i <= m; ++i) printf("%d\n",print[i]);
}

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/82560919
今日推荐