wmz的数数(数状数组)
wmz的数数(数状数组)
题目描述
\(wmz\)从小就显现出了过人的天赋,他出生的第三天就证明了哥德巴赫猜想,第五天就证明了质能方程,出生一星期之后,他觉得\(P\)是否等于\(NP\)这个问题比前面他证明的这些定理好玩多了,于是他成为了一名计算机科学家。
在他开始接触计算机科学的第一天,他就已经刷遍了所有\(oj\),这为他今后建立王国推行全民刷题计划打下了坚实的基础。在他接触计算机科学一星期之后,他就已经通读了所有顶级会议的\(paper\),并且在多方面同时出了许多成果。
他对他王国的国民智商有非常高的要求,他为想加入他的王国国籍的人准备了很多试题去测试智商,但因为他接触计算机科学第一天学到的东西就已经超过正常人一生的水平了,所以他出的试题水平在他接触计算机科学\(1\)分钟以内的水平。
-------------------------------------------吹牛分割线------------------------------------------------
\(wmz\)拥有一个长度为\(n\)的数字序列,他向你询问了\(q\)个问题,每个问题都是告诉你两个数\(L\)和\(R\),问你在序列的第\(L\)到第\(R\)个数的这一段序列中,有多少个数字\(k\),满足在这一段中恰好出现了\(k\)次。
输入格式
输入的第一行为两个整数\(n\),\(q\),表示序列的长度和问题的个数。
接下来一行有\(n\)个整数,表示\(wmz\)的数字序列。
接下来\(q\)行,每行有两个整数\(L\),\(R\),其含义如题目中所示。
输出格式
输出共\(q\)行,每行有一个整数,表示第\(i\)个问题的答案。
样例
样例输入
7 2
3 1 2 2 3 3 7
1 7
3 4
样例输出
3
1
数据范围与提示
对于\(30\%\)的数据,保证\(1 \leq n,q \leq 100\);
对于\(70\%\)的数据,保证\(1 \leq n,q \leq 10^5\);
对于\(100\%\)的数据,保证\(1 \leq n,q \leq 10^6\),序列中的每个数都在\([1,n]\)范围内
分析
用莫队离线处理可以拿到\(70\)分
然而对于\(10^6\)的数据显然会超时
\(100\)分的做法要维护一个数组\(t[i]\),代表如果选择\(i\)这个位置上的数,答案将会增加\(t[i]\)
对于一个区间来说,如果在区间中有某一个数\(i\),它在位置\(x\)上恰好是第\(i\)次出现,那么我们需要将\(t[x]\)加一
如果它在位置\(y\)上恰好是第\(i+1\)次出现,那么我们需要将\(t[y]\)减一
每次询问的答案就是询问区间中\(t\)数组的和
因为对于左端点不同的区间,某一个数\(i\)第几次出现的位置是不同的
因此我们将左端点从大到小排序,用一个代表左端点的指针向左扫
每次扫到一个值时,我们要先把上一次对这个值的操作撤销,然后看它是否满足加一或者减一的条件,对其进行新的操作
区间求和用数状数组维护即可
代码
#include<cstdio>
#include<vector>
#include<algorithm>
const int maxn=1e6+5;
std::vector<int>g[maxn];
inline int read(){
int x=0,fh=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
int n,q,a[maxn],ans[maxn],tr[maxn],sygz[maxn],sygy[maxn];
struct jl{
int l,r,id;
}b[maxn];
bool cmp(jl aa,jl bb){
return aa.l>bb.l;
}
int ef(int val,int wz){
int l=1,r=g[val].size(),mids;
while(l<=r){
mids=(l+r)>>1;
if(g[val][mids-1]>wz) r=mids-1;
else if(g[val][mids-1]<wz) l=mids+1;
else return mids;
}
return 0;
}//二分查找当前数是第几次出现
int lb(int xx){
return xx&-xx;
}
void ad(int wz,int val){
for(int i=wz;i<maxn;i+=lb(i)){
tr[i]+=val;
}
}
int qh(int wz){
int anss=0;
for(int i=wz;i>0;i-=lb(i)){
anss+=tr[i];
}
return anss;
}
int main(){
n=read(),q=read();
for(int i=1;i<=n;i++){
a[i]=read();
g[a[i]].push_back(i);
}
for(int i=1;i<=q;i++){
b[i].l=read(),b[i].r=read();
b[i].id=i;
}
std::sort(b+1,b+1+q,cmp);
int latl=n+1;//维护指针
for(int i=1;i<=q;i++){
while(latl>b[i].l){
latl--;
int wz=ef(a[latl],latl);
int tail=wz+a[latl]-1;
if(sygz[a[latl]]!=0) ad(sygz[a[latl]],-1);
if(sygy[a[latl]]!=0) ad(sygy[a[latl]],1);
//撤销上一次操作
if(tail>g[a[latl]].size()) continue;
else if(tail==g[a[latl]].size()){
ad(g[a[latl]][tail-1],1);
sygz[a[latl]]=g[a[latl]][tail-1];
sygy[a[latl]]=0;
}
else {
ad(g[a[latl]][tail-1],1);
ad(g[a[latl]][tail],-1);
sygz[a[latl]]=g[a[latl]][tail-1];
sygy[a[latl]]=g[a[latl]][tail];
}
}
ans[b[i].id]=qh(b[i].r)-qh(b[i].l-1);
}
for(int i=1;i<=q;i++){
printf("%d\n",ans[i]);
}
return 0;
}
wmz的数数(数状数组)的更多相关文章
- hdoj 1166 敌兵布阵 线段数和树状数组
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- SCAU-1144 数星星-HDU-1166-树状数组的应用
本文借鉴代码提供:https://www.cnblogs.com/geek1116/p/5566709.html树状数组详解:https://www.cnblogs.com/xenny/p/97396 ...
- BZOJ 2120 数颜色(树状数组套主席树)
1A啊,激动. 首先,不修改的情况下可以直接用主席树搞,修改的话,直接用主席树搞一次修改的情况下复杂度是O(nlogn)的. 就像你要求区间和一样,用前缀和查询是O(1),修改是O(n),只不过主席树 ...
- 树状数组求逆序对:POJ 2299、3067
前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换 ...
- FZU 2029 买票问题 树状数组+STL
题目链接:买票问题 思路:优先队列维护忍耐度最低的人在队首,leave操作ok. vis数组记录从1到n的编号的人们是不是在队列中,top维护队首的人的编号.pop操作搞定. 然后,check操作就是 ...
- HDU 5775 树状数组
Bubble Sort Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- Ping pong(树状数组经典)
Ping pong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- poj2299树状数组入门,求逆序对
今天入门了树状数组 习题链接 https://blog.csdn.net/liuqiyao_01/article/details/26963913 离散化数据:用一个数组来记录每个值在数列中的排名,不 ...
- 【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组
题目描述 给出两个长度分别为n.m的序列A.B,求出B的所有长度为n的连续子序列(子串),满足:序列中第i小的数在序列的Ai位置. 输入 第一行包含两个整数n, m (2≤n≤m≤1000000). ...
- Codeforces Round #401 (Div. 1) C(set+树状数组)
题意: 给出一个序列,给出一个k,要求给出一个划分方案,使得连续区间内不同的数不超过k个,问划分的最少区间个数,输出时将k=1~n的答案都输出 比赛的时候想的有点偏,然后写了个nlog^2n的做法,T ...
随机推荐
- swagger2打开doc页面时报错
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2& ...
- 简单的 Nginx+Tomcat 配置负载均衡集群
简单 Nginx+Tomcat 配置负载均衡集群 前期准备 解压两个tomcat,修改端口号 server1:8081 server:8082 同时启动 nginx官网下载解压版nginx 创建一个简 ...
- Vue3 为何使用 Proxy 实现数据监听
博客地址:https://ainyi.com/93 vue3 响应式数据放弃了 Object.defineProperty,而使用Proxy来代替它 我们知道,在 vue2 中,实现数据监听是使用Ob ...
- java循环语句while与do-while
一 while循环 while循环语句和选择结构if语句有些相似,都是根据条件判断来决定是否执行大括号内的执行语句. 区别在于,while语句会反复地进行条件判断,只要条件成立,{}内的执行语句就会执 ...
- 攻防世界-web(进阶)-upload1
打开链接是一个上传文件的窗口,随便上传一个PDF文件提示必须上传图片,查看源代码,要求必须输入png或jpg格式文件才会上传成功,想到通过修改源代码删除上传限制条件,上传一句话木马,通过中国菜刀进入后 ...
- 详解Python Graphql
前言 很高兴现在接手的项目让我接触到了Python Graphql,百度上对其介绍相对较少也不够全面,几乎没有完整的中文文档,所以这边也借此机会学习一下Graphql. 什么是Graphql呢? Gr ...
- three.js 利用uv和ThreeBSP制作一个快递柜
最近有three网友,问我要不要学习blender,其实我感觉学习一下也无妨,不过花大量时间精通,尚可不必,术业有专攻给别人留一条路吧,哈哈.那我我们就是用ThreeBSP和uv贴图的知识来制作一个定 ...
- Flutter简介
Flutter简介 Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台.高保真.高性能.开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平 ...
- 关于haar特征的理解及使用(java实现)
Haar特征原理综述Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征.它分为三类:边缘特征.线性特征.中心特征和对角线特征.如下所示: Haar-like矩形特征拓展 Lienha ...
- 贫血模型和DDD模型
贫血模型和DDD模型 1.贫血模型 1.1 概念 常见的mvc三层架构 简单.没有行为 2.领域驱动设计 2.1 概念(2004年提出的) Domain Driven Design 简称 DDD DD ...