luogu P3709大爷的字符串题

lxl出的又一道毒瘤题,题目本身让人读不懂,然而实际上题面用一句话就可以总结:

给你n个数,m次询问区间[l,r]中众数的出现次数

然后就用普通的莫队就好啦~~(数据也没有那么毒瘤)

#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn = 200200;
int pos[maxn], num[maxn];
int ans[maxn];
int flag[maxn];
int a[maxn], A[maxn];
int n, m, block;
int L = 0, R = 0;
int Ans = 0;
struct node{
    int l, r ,id;
    inline bool operator < (const node &x) const {
    return l / block == x.l / block ? r < x.r : l / block < x.l / block;
  }
}Q[maxn];

inline void add(int x)
{
    num[flag[a[x]]]--;
    num[++flag[a[x]]]++;
    Ans = max(Ans,flag[a[x]]);
}
inline void del(int x)
{
    if(flag[a[x]] ==Ans && num[flag[a[x]]] == 1)
    Ans--;
    num[flag[a[x]]]--;
    num[--flag[a[x]]]++;
}
int main()
{
    scanf("%d %d", &n, &m);
    block = sqrt(m);
    int N = n;
    for(int i = 1;i <= n;i++)
    {
        scanf("%d", &a[i]);
        A[i] = a[i];
    }
    sort(A + 1,A + n + 1);
    n = unique(A + 1,A + n + 1) - A - 1;
    for(int i = 1;i <= N;i++)
    a[i] = lower_bound(A + 1,A + n + 1,a[i]) - A;
    for(int i = 1;i <= m;i++)
    {
        scanf("%d %d", &Q[i].l, &Q[i].r);
        Q[i].id = i;
    }
    sort(Q + 1, Q + 1 + m);
    for(int i = 1;i <= m;i++)
    {
        while(L < Q[i].l) del(L++);
        while(L > Q[i].l) add(--L);
        while(R < Q[i].r) add(++R);
        while(R > Q[i].r) del(R--);
        ans[Q[i].id] = -Ans;
    }
    for(int i = 1;i <= m;i++)
    printf("%d\n", ans[i]);
    return 0;
}

我竟然因为在原先模版中的flag[0] = 1;没有删去只得了20分QAQ。

原文地址:https://www.cnblogs.com/jiqimin/p/10628310.html

时间: 2024-11-03 22:30:24

luogu P3709大爷的字符串题的相关文章

luogu P3709 大爷的字符串题

二次联通门 : luogu P3709 大爷的字符串题 /* luogu P3709 大爷的字符串题 莫队 看了半天题目 + 题解 才弄懂了要求什么... 维护两个数组 一个记录数字i出现了几次 一个记录出现了i次的有几个数.. */ #include <algorithm> #include <cstdlib> #include <cstdio> #include <cmath> #define Max 200090 void read (int &

洛谷 P3709 大爷的字符串题

https://www.luogu.org/problem/show?pid=3709 题目背景 在那遥远的西南有一所学校 /*被和谐部分*/ 然后去参加该省省选虐场 然后某蒟蒻不会做,所以也出了一个字符串题: 题目描述 给你一个字符串a,每次询问一段区间的贡献 贡献定义: 每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S 如果S为空,你rp减1 如果S中有一个元素不小于x,则你rp减1,清空S 之后将x插入S 由于你是大爷,平时做过的题考试都会考到,所以每次询问

P3709 大爷的字符串题(50分)

题目背景 在那遥远的西南有一所学校 /*被和谐部分*/ 然后去参加该省省选虐场 然后某蒟蒻不会做,所以也出了一个字符串题: 题目描述 给你一个字符串a,每次询问一段区间的贡献 贡献定义: 每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S 如果S为空,你rp减1 如果S中有一个元素不小于x,则你rp减1,清空S 之后将x插入S 由于你是大爷,平时做过的题考试都会考到,所以每次询问你搞完这段区间的字符之后最多还有多少rp?rp初始为0 询问之间不互相影响~ 输入输出格

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

题目链接 语文题啊…… 看题解发现是让求区间中最多的数的个数,于是果断理解了一会题解……莫队套上完事. sum[i]表示i这个数出现的次数,cnt[i]表示出现i次的数有几个,然后乱搞搞……就好了 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cctype> #include<cmath> #define maxn 3

[P3709] 大爷的字符串题

Link: P3709 传送门 Solution: lxl出的语文题 其实转化一下就是求将当前区间最少拆分成多少个严格单调上升序列(可不连续) 再转化一下就是求区间内的众数个数 本来求众数的套路是主席树+二分 但此题不要求在线,用莫队同时维护$i$的出现次数$cnt[i]$和出现次数为$i$的数的个数$sum[i]$ 这样常规套路更新结果就好了 Code: #include <bits/stdc++.h> using namespace std; const int MAXN=5e5+10;

大爷的字符串题 莫队

大爷的字符串题 莫队 首先这不是一道字符串题.需要仔细研究题的性质,我们会发现答案即为区间众数的个数,因为我们可以将区间分为众数个递增数列,这样为最优. 所以问题转换为求区间众数个数.使用莫队. #include <cstdio> #include <algorithm> #include <cmath> #define MAXN 400020 using namespace std; int ans,a[MAXN],cnt[MAXN],sum[MAXN]; inlin

大爷的字符串题

莫队水毒瘤题 出题人语文水平极高,题意理解一下 就是求区间众数出现次数(什么毒瘤题目) #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5211314; int a[maxn], pos[maxn], s[maxn],d[maxn]; int cnt[maxn],ans[maxn],lx,n,m; int re(){ int x=0,w=1;char ch=getchar(

luogu P1072 Hankson的趣味题

题目链接 luogu P1072 Hankson 的趣味题 题解 啊,还是noip的题好做 额,直接推式子就好了 \(gcd(x,a_0)=a_1=gcd(\frac{x}{a_1},\frac{a_0}{a_1})\) 额....上面这个式子似乎没用,看b的 \(lcm(x,b_0)=\frac{x*b_0}{gcd(x,b_0)}=b1\) 那么\(gcd(x,b_0)=\frac{x*b_0}{b_1}\) \(gcd(\frac{b_1}{b_0},\frac{b_1}{x})=1\)

[Luogu P4173]残缺的字符串 ( 数论 FFT)

题面 传送门:洛咕 Solution 这题我写得脑壳疼,我好菜啊 好吧,我们来说正题. 这题.....emmmmmmm 显然KMP类的字符串神仙算法在这里没法用了. 那咋搞啊(或者说这题和数学有半毛钱关系啊) 我们考虑把两个字符相同强行变为一个数学关系,怎么搞呢? 考虑这题是带通配符的,我们可以这样设: \(C(x,y)=(A[x]-B[y])^2*A[x]*B[y]\) 因此,我们可以看出两个字符一样当且仅当\(C(x,y)=0\) 因此,我们再设一个函数\(P(x)\)表示\(B\)串以第\