zoukankan      html  css  js  c++  java
  • P3709 大爷的字符串题 莫队

    题目链接

    题意:

    就是让你找那个众数在询问的区间内出现了多少次,就比如样例:

    3 3
    3 3 3
    3 3
    3 3
    3 3

    他询问你[3,3]这个区间的值,我们可以看出来3就是那个众数,这个数在[3,3]区间内出现了1次,所以np(np原本为0)就减去1,所以输出-1

    至于为什么是求众数?可以看:

    就比如说这个数列1,1,1,2,2,4,5,6,6,71,1,1,2,2,4,5,6,6,7

    我们把它排成一段一段的递增序列可以使rprp掉的最少

    就变成了1,2,4,5,6,7,1,2,6,11,2,4,5,6,7,1,2,6,1共掉3点rprp

    然后发现递增序列的个数就等于区间众数的出现次数

    求众数,我们就需要维护最大值(之前做了一道回滚莫队,我一看维护最大值就感觉是回滚莫队,难搞 -_-)。普通莫队就可以解决它

    我们用一个cnt数组来记录一个数出现的次数,再使用sum[i]数组来记录有多少数出现了i次

    这个样子的话我们使用maxx来维护最大值,如果添加元素,那就每次比较取最大

    maxx=max(maxx,cnt[typ[l]]);

    如果删除元素,如果满足下面的判断,就让maxx减去1

    if(cnt[typ[r]]==maxx && sum[cnt[typ[r]]]==1)
                {
                    maxx--;
                }

    代码:

    #include <map>
    #include <set>
    #include <list>
    #include <queue>
    #include <deque>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 2e5+10;
    const int INF = 0x3f3f3f3f;
    const double PI = 3.1415926;
    const long long N = 1000006;
    const double eps = 1e-10;
    typedef long long ll;
    #define mem(A, B) memset(A, B, sizeof(A))
    #define lson rt<<1 , L, mid
    #define rson rt<<1|1 , mid + 1, R
    #define ls rt<<1
    #define rs rt<<1|1
    #define SIS std::ios::sync_with_stdiget_mod_new(z-x)o(false), cin.tie(0), cout.tie(0)
    #define pll pair<long long, long long>
    #define lowbit(abcd) (abcd & (-abcd))
    #define max(a, b) ((a > b) ? (a) : (b))
    #define min(a, b) ((a < b) ? (a) : (b))
    inline int read() {  //读取整数
        int res = 0;
        char c = getchar();
        while(!isdigit(c)) c = getchar();
        while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
        return res;
    }
    struct Node{
        int l,r,id;
    }node[maxn];
    int arr[maxn],ans[maxn],belong[maxn],sizes,new_size,cnt[maxn],inp[maxn],typ[maxn],sum[maxn];
    bool cmp(Node a,Node b)
    {
        return (belong[a.l]^belong[b.l]?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r));
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        sizes=sqrt(n);
        new_size=ceil((double)n/sizes);
        for(int i=1; i<=n; ++i)
            arr[i]=inp[i]=read();
        sort(inp+1,inp+1+n);
        int tot=unique(inp+1,inp+1+n)-inp-1;
        for(int i=1; i<=n; ++i)
        {
            typ[i]=lower_bound(inp+1,1+inp+tot,arr[i])-inp;
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&node[i].l,&node[i].r);
            node[i].id=i;
        }
        for(int i=1;i<=new_size;++i)
        {
            for(int j=(i-1)*sizes+1;j<=i*sizes;++j)
            {
                belong[j]=i;
            }
        }
        sort(node+1,node+1+m,cmp);
        int l=1,r=0,maxx=0;
        for(int i=1;i<=m;++i)
        {
            int start=node[i].l,last=node[i].r;
            while(l<start)
            {
                if(cnt[typ[l]]==maxx && sum[cnt[typ[l]]]==1)
                {
                    maxx--;
                }
                sum[cnt[typ[l]]]--;
                cnt[typ[l]]--;
                sum[cnt[typ[l]]]++;
                l++;
            }
            while(l>start)
            {
                l--;
                sum[cnt[typ[l]]]--;
                cnt[typ[l]]++;
                sum[cnt[typ[l]]]++;
                maxx=max(maxx,cnt[typ[l]]);
            }
            while(r>last)
            {
                if(cnt[typ[r]]==maxx && sum[cnt[typ[r]]]==1)
                {
                    maxx--;
                }
                sum[cnt[typ[r]]]--;
                cnt[typ[r]]--;
                sum[cnt[typ[r]]]++;
                r--;
            }
            while(r<last)
            {
                r++;
                sum[cnt[typ[r]]]--;
                cnt[typ[r]]++;
                sum[cnt[typ[r]]]++;
                maxx=max(maxx,cnt[typ[r]]);
            }
            ans[node[i].id]=maxx;
        }
        for(int i=1;i<=m;++i)
            printf("%d
    ",-ans[i]);
        return 0;
    }

    题目背景

    在那遥远的西南有一所学校,

    /*被和谐部分*/

    然后去参加该省省选虐场,

    然后某蒟蒻不会做,所以也出了一个字符串题:

    题目描述

    给你一个字符串 aa,每次询问一段区间的贡献。

    贡献定义:

    每次从这个区间中拿出一个字符 xx ,然后把 xx 从这个区间中删除,直到区间为空。你要维护一个集合 SS

    • 如果 SS 为空,你 rp 减 11
    • 如果 SS 中有一个元素不小于 xx,则你 rp 减 11,清空 SS
    • 之后将 xx 插入 SS

    由于你是大爷,平时做过的题考试都会考到,所以每次询问你搞完这段区间的字符之后最多还有多少 rp?rp 初始为 00

    询问之间不互相影响~

    输入格式

    第一行两个整数 nnmm,表示字符串长度与询问次数。

    之后一行 nn 个数,第 ii 个整数表示给出的字符串的第 ii 个字符 x_ixi

    接下来 mm 行,每行两个整数 l, rl,r,表示一次询问的区间。

    输出格式

    对于每次询问,输出一行一个整数表示答案。

    输入输出样例

    输入 #1
    3 3
    3 3 3
    3 3
    3 3
    3 3
    输出 #1
    -1
    -1
    -1

    说明/提示

    数据规模与约定

    • 对于 10\%10% 的数据,是样例。
    • 对于另外 10\%10% 的数据,保证 n,m le 100n,m100
    • 对于另外 10\%10% 的数据,保证 n,m le 10^3n,m103
    • 对于另外 10\%10% 的数据,保证 n,m le 10^4n,m104
    • 对于另外 10\%10% 的数据,保证 n,m le 10^5n,m105
    • 对于 100\%100% 的数据,1 leq n,m le 2 imes10^51n,m2×1051 leq a_i leq 10^91ai1091 leq l, r leq n1l,rn
  • 相关阅读:
    记最近的玄学东西
    AGC032F One Third
    【集训队作业2018】小Z的礼物
    Codeforces 1214 F G H 补题记录
    如何使用Spark大规模并行构建索引
    一次bug死磕经历之Hbase堆内存小导致regionserver频繁挂掉
    ElasticSearch中分词器组件配置详解
    Hadoop2.7.1配置NameNode+ResourceManager高可用原理分析
    分布式日志收集之Logstash 笔记(一)
    海量可视化日志分析平台之ELK搭建
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13730658.html
Copyright © 2011-2022 走看看