• P3709 大爷的字符串题(莫队+离散化)


    P3709 大爷的字符串题

    题目背景

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

    /被和谐部分/

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

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

    题目描述

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

    贡献定义:

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

    • 如果 (S) 为空,你 (rp)(1)
    • 如果 (S) 中有一个元素不小于 (x),则你 (rp)(1),清空 (S)
    • 之后将 (x) 插入 (S)

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

    询问之间不互相影响~

    输入格式

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

    之后一行 (n) 个数,第 (i) 个整数表示给出的字符串的第 (i) 个字符 (x_i)

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

    输出格式

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

    输入输出样例

    输入 #1

    3 3
    3 3 3
    3 3
    3 3
    3 3

    输出 #1

    -1
    -1
    -1

    说明/提示

    数据规模与约定

    • 对于 (10\%) 的数据,是样例。
    • 对于另外 (10\%) 的数据,保证 (n,m le 100;)
    • 对于另外 (10\%) 的数据,保证 (n,m le 10^3;)
    • 对于另外 (10\%) 的数据,保证 (n,m le 10^4;)
    • 对于另外 (10\%) 的数据,保证 (n,m le 10^5;)
    • 对于 (100\%) 的数据,(1 leq n,m le 2 imes10^5,1 leq a_i leq 10^9,1 leq l, r leq n。)

    保证数据像某省省选 day1T2 一样 sb,大家尽情用暴力水过题吧!

    没事,你只要在一个好学校,就算这题只能拿到 10 分,也可以进队了。

    Solution

    唔,其实这是道语文题,题目要求
    给定一个区间,求区间内众数的出现次数

    为啥是这样,我们看这样一个样例

    111122233345
    12345/123/123/1
    

    可以发现我们把序列排成一段一段的递增序列是最优的,每进入新的一段,(rp)就会-1
    段落数也就是求出现次数最多的数的出现次数,因为后面段落出现的数一定也在前面的段落中出现过

    用莫队求解
    我们用(cnt[x])表示(x)的出现次数,很明显在(add())(ans=max(ans,cnt[x]))

    但是删除的时候,可能会遇到这样一个问题,当前的(cnt[x])恰好就等于(ans),那我们能直接使(ans--)吗?不能!因为可能还有其他的(cnt[y])也等于(ans),删掉一个(x)不足以改变我们的答案

    所以现在还要开一个数组(p[cnt]),表示出现次数为(cnt)的数字有多少个
    (remove())函数中,如果当前的(cnt[x]==ans)并且(p[cnt[x]]==1),我们才能使ans--

    嗷,有一个细节,这道题的值域范围是(10^9),需要离散

    Code

    #include<bits/stdc++.h>
    #define il inline
    #define rg register
    #define lol long long
    #define in(i) (i=read())
    using namespace std;
    
    const  int N=2e5+5;
    
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
        return ans*f;
    }
    
    int n,m,k,block,ans;
    int a[N],sum[N],cnt[N],p[N],b[N];
    
    struct query{
    	int l,r,id,pos;
    	bool operator < (const query &a) const {
    		return pos==a.pos?r<a.r:pos<a.pos;
    	}
    }t[N];
    
    void add(int x) {
    	p[cnt[a[x]]]--;
    	cnt[a[x]]++;
    	p[cnt[a[x]]]++;
    	ans=max(ans,cnt[a[x]]);
    }
    
    void remove(int x) {
    	if(p[cnt[a[x]]]==1 && ans==cnt[a[x]]) ans--;
    	p[cnt[a[x]]]--;
    	cnt[a[x]]--;
    	p[cnt[a[x]]]++;
    }
    
    int main() {
    	in(n), in(m); block=3*sqrt(n);
    	for (rg int i=1;i<=n;i++) in(a[i]),b[i]=a[i];
    	sort(b+1,b+1+n); int len=unique(b+1,b+1+n)-b-1;
    	for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+len,a[i])-b;
    	for (rg int i=1,l,r;i<=m;i++)  {
    		in(l), in(r);
    		t[i].l=l, t[i].r=r;
    		t[i].id=i;
    		t[i].pos=(l-1)/block+1;
    	}
    	sort(t+1,t+1+m);
    	for (rg int i=1,curl=1,curr=0;i<=m;i++) {
    		rg int l=t[i].l,r=t[i].r;
    		while(curl<l) remove(curl++);
    		while(curl>l) add(--curl);
    		while(curr<r) add(++curr);
    		while(curr>r) remove(curr--);
    		sum[t[i].id]=-ans;
    	}
    	for (rg int i=1;i<=m;i++) cout<<sum[i]<<endl;
    }
    
    博主蒟蒻,随意转载.但必须附上原文链接
    http://www.cnblogs.com/real-l/
  • 相关阅读:
    Python学习笔记21:数据库操作(sqlite3)
    JAVA的extends使用方法
    thinkphp5的Illegal string offset 'id'错误
    thinkphp5项目--个人博客(五)
    语法错误: unexpected ''); ?></span></span></h2> ' (T_CONSTANT_ENCAPSED_STRING), expecting ',' or ';'
    thinkphp5.0的验证码安装和相关错误
    thinkphp5项目--个人博客(四)
    thinkphp5项目--个人博客(三)
    NAS是什么
    百度编辑器简介及如何使用
  • 原文地址:https://www.cnblogs.com/real-l/p/15171668.html
Copyright © 2020-2023  润新知