zoukankan      html  css  js  c++  java
  • [洛谷3709]大爷的字符串题(区间众数)

    题目描述

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

    贡献定义:

    每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S

    如果S为空,你rp减1

    如果S中有一个元素不小于x,则你rp减1,清空S

    之后将x插入S

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

    询问之间不互相影响~

    输入输出格式

    输入格式:

    第一行两个数n,m,表示字符串长度与询问次数

    之后一行n个数,表示字符串

    由于你是大爷,所以字符集1e9

    之后m行每行两个数,表示询问的左右区间

    输出格式:

    m行,每行一个数表示答案

    输入输出样例

    输入样例#1: 
    3 3
    3 3 3
    3 3
    3 3
    3 3
    输出样例#1: 
    -1
    -1
    -1

    说明

    前4个点1s,后面的点4s

    对于10%的数据,是样例

    对于另外10%的数据,n,m <= 100

    对于另外10%的数据,n,m <= 1000

    对于另外10%的数据,n,m <= 10000

    对于另外10%的数据,n,m <= 100000

    对于100%的数据,n,m <= 200000

    题意很难懂啊

    题意:求严格上升子序列的最少个数,每个数只能在一个子序列中且每个数的顺序可以自由交换,答案为个数*-1(即1 3 3 2的答案是-2),然后给出几个询问,每次询问一个区间,求最少个数。

    我们发现严格上升子序列的最少个数取决于相同数字的出现个数。即严格上升子序列的最少个数为询问的区间内的众数的出现次数

    莫队

    由于数字最大可以是1e9,所以我们要先离散化

    我们用cnt[i]表示数i的出现次数,用num[i]表示出现i次的数字个数,sum表示出现次数最多的数的出现次数(即众数的出现次数)

    对于把区间向左,向右扩展一个数,我们判断扩展那个数的出现次数是不是当前区间内众数的出现次数(cnt[i]==sum),是则更新众数的出现次数(sum++),然后更新num,cnt什么的

    对于把区间最左边(右边)删除一个数,我们判断删除那个数的出现次数是不是当前区间内众数的出现次数(cnt[i]==sum),是则再判断这个出现次数是不是只有这一个数(num[i]==1),若是,则意味着区间众数的出现次数变少(sum--),然后更新num,cnt什么的

    num[0]的初始值要设成数字的种类数(即出现了多少种的不同数字 1 3 3 2 num[0]=3),我们可以理解为初始[l,r]区间内,有这么多个数出现了0次

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct xxx{
        int l,r,block,id;
    }q[200001];
    struct xxx2{
        int val,id;
    }a[200001];
    int b[200001],cnt[200001],num[200001],ans[200001];
    bool cmp(xxx a,xxx b){if(a.block!=b.block)return a.block<b.block;return a.r<b.r;}
    bool cmp2(xxx2 a,xxx2 b){return a.val<b.val;}
    int main()
    {
        int n,m;scanf("%d%d",&n,&m);int T=(int)sqrt((double)n);
        for(int i=1;i<=n;i++){scanf("%d",&a[i].val);a[i].id=i;}
        sort(a+1,a+n+1,cmp2);int last=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i].val!=a[i-1].val)last++;
            b[a[i].id]=last;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;q[i].block=(q[i].l+1)/T;
        }
        sort(q+1,q+m+1,cmp);
        int l=1,r=0,sum=0;num[0]=last;
        for(int i=1;i<=m;i++)
        {
            while(r<q[i].r){r++;if(cnt[b[r]]==sum)sum++;num[cnt[b[r]]]--;cnt[b[r]]++;num[cnt[b[r]]]++;}
            while(r>q[i].r){if(cnt[b[r]]==sum&&num[cnt[b[r]]]==1)sum--;num[cnt[b[r]]]--;cnt[b[r]]--;num[cnt[b[r]]]++;r--;}
            while(l<q[i].l){if(cnt[b[l]]==sum&&num[cnt[b[l]]]==1)sum--;num[cnt[b[l]]]--;cnt[b[l]]--;num[cnt[b[l]]]++;l++;}
            while(l>q[i].l){l--;if(cnt[b[l]]==sum)sum++;num[cnt[b[l]]]--;cnt[b[l]]++;num[cnt[b[l]]]++;}
            ans[q[i].id]=sum;
        }
        for(int i=1;i<=m;i++)printf("%d
    ",-ans[i]);
        return 0;
    } 
  • 相关阅读:
    开始系统的研究区块链技术了
    基于Centos7的比特币源码编译
    WTForms
    flask-session
    抽屉之Tornado实战(5)--点赞与评论树
    零碎知识点
    flask信号
    MetaClass
    flask系列
    flask源码剖析--请求流程
  • 原文地址:https://www.cnblogs.com/lher/p/7828666.html
Copyright © 2011-2022 走看看