题目描述

给定一个元素个数为 n 的整数数组 a 和 Q 个问题,每个问题有 x,y 两个参数,请统计共有多少个整数 K 满足 K 在 a[x]…a[y] 中出现了恰好 K 次。

输入格式

第一行两个整数 n,Q,表示数组 a 的元素个数和询问数;

接下来一行 n 给整数,描述数组 a ;

接下来 Q 行,每行两个数 xi,yi(1≤xi≤yi≤n),表示询问的左右边界。

输出格式

输出 Q 行,每行一个整数表示满足询问的 K 的个数。

样例数据 1

输入

7 2

3 1 2 2 3 3 7

1 7

3 4

输出

3

1

备注

样例说明

Q1: 1、2、3 分别满足,所以共有 3 个数满足要求。

Q2: 2 满足,所以只有 1 个数满足要求。

数据范围

对 50% 的输入数据:1≤n,Q≤1000

对 100% 的输入数据:1≤n,Q≤100000,1≤a[i]≤109

题目分析

莫队裸题,因为不熟练所以第一次没有分块,导致时间复杂度退化。

一定要分块!!!

莫队的时间复杂度证明:

右端点移动:

首先我们考虑一个块里面的转移情况

由于一个块里面的询问都按右端点排序

所以我们右端点在一个块里面最多移动n次

有 O(√n)个块,那么同一个块内的右端点移动最多就是O(n√n)

然后考虑从一个块到另一个块导致的右端点变化

最坏情况,右端点由n到1,那么移动n次

有 O(√n)个块

那么从一个块到另一个块的事件只会发生O(√n)次……

所以这种右端点移动的次数也是O(n√n)次

没有别的事件导致右端点移动了

左端点移动:

同一个块里面,由于左端点都在一个长度为O(√n)的区间里面

所以在同一块里面移动一次,左端点最多变化O(√n)

总共有n个询问……

所以同一块里面的移动最多n次

那么同一个块里面的左端点变化最多是O(n√n)的

考虑跨越块

每由第i个块到第i+1个块,左端点最坏加上O(√n)

总共能加上O(√n)次

所以跨越块导致的左端点移动是O(n)的

综上,分块做法是O(n∗√n)。

code

#include<iostream>
#include<cstdio>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std; const int N = 100000;
int n, Q, cnt[N + 5], ans;
int a[N + 5], b[N + 5], len, ret[N + 5];
bool vst[N + 5];
int S;
struct node{
int x, y, id, bl;
node(){}
node(int _x, int _y, int o, int b):x(_x), y(_y), id(o), bl(b){}
inline bool operator < (const node &p) const{
if(bl != p.bl) return bl < p.bl;
return y < p.y;
}
}qry[N + 5]; inline int read(){
int i = 0, f = 1; char ch = getchar();
for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; ch >= '0'&& ch <= '9'; ch = getchar())
i = (i << 1) + (i << 3) + (ch - '0');
return i * f;
} inline void disc_init(){
sort(b + 1, b + n + 1);
len = unique(b + 1, b + n + 1) - (b + 1);
for(int i = 1; i <= n; i++){
a[i] = lower_bound(b + 1, b + len + 1, a[i]) - b;
cnt[a[i]]++;
}
} inline void wr(int x){
if(x < 0) x = -x, putchar('-');
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
} int main(){
// freopen("count.in", "r", stdin);
// freopen("count.out", "w", stdout);
n = read(), Q = read();
S = sqrt(n);
for(int i = 1; i <= n; i++) a[i] = b[i] = read();
for(int i = 1; i <= Q; i++){
int x = read(), y = read();
qry[i] = node(x, y, i, (x - 1) / S + 1);
}
sort(qry + 1, qry + Q + 1);
disc_init();
for(int i = 1; i <= n; i++){
if(vst[a[i]]) continue;
vst[a[i]] = true;
if(cnt[a[i]] == b[a[i]])
ans++;
}
int head = 1, tail = n;
for(int i = 1; i <= Q; i++){
int x = qry[i].x, y = qry[i].y;
while(head > x){
head--;
if(cnt[a[head]] == b[a[head]]) ans--;
cnt[a[head]]++;
if(cnt[a[head]] == b[a[head]]) ans++;
}
while(head < x){
if(cnt[a[head]] == b[a[head]]) ans--;
if(cnt[a[head]] - 1 == b[a[head]]) ans++;
cnt[a[head]]--, head++;
}
while(tail > y){
if(cnt[a[tail]] == b[a[tail]]) ans--;
if(cnt[a[tail]] - 1 == b[a[tail]]) ans++;
cnt[a[tail]]--, tail--;
}
while(tail < y){
tail++;
if(cnt[a[tail]] == b[a[tail]]) ans--;
cnt[a[tail]]++;
if(cnt[a[tail]] == b[a[tail]]) ans++;
}
ret[qry[i].id] = ans;
} for(int i = 1; i <= Q; i++)
wr(ret[i]), putchar('\n');
return 0;
}

NOIP模拟 - 莫队的更多相关文章

  1. [BZOJ3757]苹果树(树上莫队)

    树上莫队共有三种写法: 1.按DFS序列分块,和普通莫队类似.常数大,不会被卡. 2.按块状树的方式分块.常数小,会被菊花图卡到O(n). 3.按[BZOJ1086]王室联邦的方式分块.常数小,不会被 ...

  2. 20181009noip HZ EZ两校联考sum(莫队,组合数学)

    题面戳这里 思路: noip考莫队???!!! 考场上死活没往这方面想啊!!!数据分治忘写endl50pts滚粗了 这里每个询问都有n,m两个参数 我们可以把它看做常规莫队中的l和r 然后利用组合数的 ...

  3. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  4. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  5. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  6. 2018.11.07 NOIP训练 L的鞋子(权值分块+莫队)

    传送门 乱搞题. 我直接对权值分块+莫队水过了. 不过调了30min30min30min发现ststst表挂了是真的不想说什么233. 代码

  7. 2018.10.29 NOIP训练 数据结构(带修改莫队)

    传送门 带修莫队板题. 直接按照经典写法做就行了. 代码

  8. [Ynoi2019模拟赛]Yuno loves sqrt technology II(二次离线莫队)

    二次离线莫队. 终于懂了 \(lxl\) 大爷发明的二次离线莫队,\(\%\%\%lxl\) 二次离线莫队,顾名思义就是将莫队离线两次.那怎么离线两次呢? 每当我们将 \([l,r]\) 移动右端点到 ...

  9. 2018.10.23 NOIP训练 Leo的组合数问题(组合数学+莫队)

    传送门 好题. 考察了莫队和组合数学两个知识板块. 首先需要推出单次已知n,mn,mn,m的答案的式子. 我们令f[i]f[i]f[i]表示当前最大值为第iii个数的方案数. 显然iii之后的数都是单 ...

随机推荐

  1. 学习笔记:Vue——组件和Prop

    前言:这一篇是关于组件基础.组件注册.Prop等内容. 1.组件基础 01.组件是可复用的Vue实例 02.组件中的data选项必须是一个函数 03.一个组件默认可以有任意数量的prop 任何值都可以 ...

  2. iOS 之应用性能调优的25个建议和技巧

    注意:每在优化代码之前,你都要注意一个问题,不要养成"预优化"代码的错误习惯. 时常使用Instruments去profile你的代码来发现须要提升的方面.Matt Gallowa ...

  3. POJ 3187 Backward Digit Sums 枚举水~

    POJ 3187  Backward Digit Sums http://poj.org/problem?id=3187 题目大意: 给你一个原始的数字序列: 3   1   2   4  他可以相邻 ...

  4. App.js和App.css(用于移动应用的js和css)

    App.js和App.css(用于移动应用的js和css) 一.App.js和App.css(用于移动应用的js和css) App.js 是一个轻量级的 JavaScript UI 库,用来创建移动的 ...

  5. v-if和updated钩子结合使用 渲染echart图表

    项目需求是这样的,用户可以自定选择echart 曲线图 是横向还是竖向显示.我的做法是 写了一个横向的echart图表,也写了一个竖向的echart图表,然后两者共用存在store里的图表数据,就能实 ...

  6. thinkphp5项目--企业单车网站(九)(加强复习啊)(花了那么多时间写的博客,不复习太浪费了)

    thinkphp5项目--企业单车网站(九)(加强复习啊)(花了那么多时间写的博客,不复习太浪费了) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicyc ...

  7. 致ITFriend用户

    ) 全权处理,相关问题请和他沟通. 祝大家中秋节快乐,一家团团圆圆. 小雷FansUnion   湖北 武汉   2014年9月7日 --------------------------------- ...

  8. 基于Android Fragment功能的样例

    通过近期空暇时候对Fragment的学习,尝试着写了一个小Demo,将在开发的时候能经常使用到的Fragment知识放在一起,写过了这个Demo对Android Fragment的了解更加深入了,以后 ...

  9. NoSql中的B-tree、B+tree和LSM-tree 分类: B7_HBASE 2015-03-15 18:27 85人阅读 评论(0) 收藏

    总结: 1.B+树将数据完全排序,读数据时很快,但当要修改数据时,就需要将新入数据下面的数据重新排位,特别是当写入的数据排在较高的位置时,需要大量的移位操作才能完成写入. 2.SLM牺牲部分的读性能, ...

  10. Java中的${pageContext.request.contextPath}

    之前在drp项目中就接触了${pageContext.request.contextPath}.当时没有注意.这次在java版高校云平台ITOO4.0中再次与之相遇,真是无巧不成书啊.再次遇到.我再置 ...