题目链接

题目描述

给你一个字符串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

思路

构造

要使得扣除尽量少的\(rp\),就要使得每次操作插入的数大于原先集合中已有的数字,即保持集合的严格单调性。到万不得已的时候再重新开始。

共需重新开始的次数为出现最多的一个数出现的个数,即众数的出现次数。

故题意就是给一个序列,每次询问一个区间,问这个区间里的众数的出现次数。

莫队算法

可用莫队算法离线处理所有询问。

维护众数的出现次数:用\(cnt[i]\)维护数字\(i\)的出现次数,用\(num[i]\)维护出现了\(i\)次的数字有多少个,因此,最大的不为\(0\)的\(num[\ ]\)的下标即为众数的出现次数。

注意点

读入初始数据之后就要进行离散化。如果用\(map\)存,每次操作的时候都进行映射,这样时间代价太大。

Code

/*

下面是50分代码↓↓↓

基本上参考着Candy?大佬的从头到尾改了一遍后来又厚颜无耻地交了一发大佬的代码都还是有5组一直T十分困惑...。

就姑且先50分着吧。还是学到了不少的,比如莫队的优美写法、\(cnt\)和\(num\)的妙招、先离散化而不是用\(map\)瞎搞。

*/

#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
typedef long long LL;
int a[maxn], ans[maxn], cnt[maxn], mp[maxn], num[maxn], now, block[maxn];
struct node {
int l, r, id;
}q[maxn];
inline LL read(){
char c=getchar(); LL x=0,f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
bool cmp(node u, node v) {
return block[u.l] < block[v.l] || (block[u.l] == block[v.l] && block[u.r] < block[v.r]);
}
void add(int i) {
--num[cnt[a[i]]], ++num[++cnt[a[i]]];
while (num[now+1]) ++now;
}
void del(int i) {
--num[cnt[a[i]]], ++num[--cnt[a[i]]];
while (!num[now]) --now;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
int grp = sqrt(n);
for (int i = 1; i <= n; ++i) a[i] = mp[i] = read(), block[i] = (i-1) / grp;
sort(mp+1, mp+1+n);
int nn = unique(mp+1, mp+1+n) - (mp+1);
for (int i = 1; i <= n; ++i) a[i] = lower_bound(mp+1, mp+1+nn, a[i]) - mp; for (int i = 0; i < m; ++i) q[i].l = read(), q[i].r = read(), q[i].id = i;
sort(q, q+m, cmp); int l = 0, r = 0;
for (int i = 0; i < m; ++i) {
while (q[i].l < l) add(--l);
while (q[i].l > l) del(l++);
while (q[i].r < r) del(r--);
while (q[i].r > r) add(++r);
ans[q[i].id] = now;
} for (int i = 0; i < m; ++i) printf("%d\n", -ans[i]);
return 0;
}

luogu 3709 大爷的字符串题 构造 莫队 区间众数的更多相关文章

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

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

  2. [ Luogu 3709 ] 大爷的字符串题

    \(\\\) Description 原题题面太过混乱出题人语文凉凉 给出一个长为 \(n\) 的数列 \(A\) ,多次询问: 对于一个区间 \([L_i,R_i]\),把区间内的所有数最少划分成多 ...

  3. 洛谷P3709 大爷的字符串题(莫队)

    题目背景 在那遥远的西南有一所学校 /*被和谐部分*/ 然后去参加该省省选虐场 然后某蒟蒻不会做,所以也出了一个字符串题: 题目描述 给你一个字符串a,每次询问一段区间的贡献 贡献定义: 每次从这个区 ...

  4. P3709 大爷的字符串题 脑子+莫队

    简化题意:区间众数出现次数??? 为什么?原因是,贪心的想,我们要划分成尽量少的严格递增序列,这样rp掉的最少. 设区间众数出现次数为 \(x\) ,那我们至少要分成 \(x\) 段严格上升序列. # ...

  5. luogu P3709 大爷的字符串题

    二次联通门 : luogu P3709 大爷的字符串题 /* luogu P3709 大爷的字符串题 莫队 看了半天题目 + 题解 才弄懂了要求什么... 维护两个数组 一个记录数字i出现了几次 一个 ...

  6. 【luogu P3709 大爷的字符串题】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3709 离散化+区间众数..? #include <iostream> #include < ...

  7. P3709 大爷的字符串题(莫队+结论)

    题目 P3709 大爷的字符串题 做法 有一个显然的结论:一段区间里最小答案为众数的个数 用莫队来离线求众数 \(tmp_i\)表示出现\(i\)次的数的个数,\(num_i\)表示\(i\)出现的次 ...

  8. P3709 大爷的字符串题 (莫队)

    题目 P3709 大爷的字符串题 题意:求\([l,r]\)中众数的个数. 解析 维护两个数组: \(cnt[x]\),数\(x\)出现的次数. \(sum[x]\),出现次数为\(x\)的数的个数. ...

  9. AC日记——大爷的字符串题 洛谷 P3709

    大爷的字符串题 思路: 莫队,需开O2,不开50: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 20000 ...

随机推荐

  1. Java迭代器问题 有100个人围成一个圈从1开始报数,报到14的这个人就要退出,然后其他人重新开始,从1报数,到14退出问:最后剩下的是100人中的第几个人 用listIterator迭代元素,并对集合进行删除操作

    package com.swift; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; ...

  2. 51nod——2504 是子序列的个数(一看就会的序列自动机原理)

    还以为序列自动机是什么,写完无意间看到帖子原来这就是序列自动机……这算自己发现算法

  3. 【线段树合并】bzoj3545: [ONTAK2010]Peaks

    1A还行 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问, ...

  4. NOIP2018 - 暑期博客整理

    暑假写的一些博客复习一遍.顺便再写一遍或者以现在的角度补充一点东西. 盛暑七月 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士 比较经典的基环外向树dp.可以借鉴的 ...

  5. DELL PowerEdge R620安装Windows server(你想将windows安装在何处”找不到任何本地磁盘,“找不到驱动器”)已解决!

    你可能碰到过DELL服务器上安装Windows server系列系统时无法识别或找不到硬盘的问题,对于DELL PowerEdge11-14代机器的,大家可以采用DELL的Lifecycle cont ...

  6. Python爬虫系列-Selenium详解

    自动化测试工具,支持多种浏览器.爬虫中主要用来解决JavaScript渲染的问题. 用法讲解 模拟百度搜索网站过程: from selenium import webdriver from selen ...

  7. centos7 rpm安装mysql5.7

    1.去官网下载指定的数据库版本:https://dev.mysql.com/downloads/mysql/ 2.根据所用的操作系统下载指定的rpm包 3.下载及安装 地址链接wget https:/ ...

  8. redis+PHP消息队列实现及应用

    学习视频: http://www.imooc.com/learn/852 学习笔记: https://blog.csdn.net/qq_33862644/article/details/7938564 ...

  9. 《linux设备驱动开发详解》笔记——10中断与时钟

    10.1 中断与定时器 中断一般有如下类型: 内部中断和外部中断:内部中断来自CPU,例如软件中断指令.溢出.除0错误等:外部中断有外部设备触发 可屏蔽中断和不可屏蔽中断 向量中断和非向量中断,ARM ...

  10. manjaro linux没有ll等命令的解决办法

    编辑~/.bashrc, 添加alias 如下 vim ~/.bashrc设置别名. 添加如下行 alias ll='ls -alF' alias la='ls -A' alias vi='vim' ...