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 ...
随机推荐
- Spark Streaming高吞吐、高可靠的一些优化
分享一些Spark Streaming在使用中关于高吞吐和高可靠的优化. 目录 1. 高吞吐的优化方式 1.1 更改序列化的方式 1.2 修改Receiver接受到的数据的存储级别 1.3 广播配置变 ...
- .Net Core中简单使用MongoDB
MongoDB 是由C++语言编写的,是一个基于分布式且面向文档存储的开源数据库系统. 下载地址: https://www.mongodb.com/download-center/community ...
- office2010的破解工具
office2010的破解工具,找了好多的密钥都不合适,直接用这个软件一键搞定, 下载地址:https://pan.baidu.com/s/1phPwihCDipGwGdSmjWNeYw 提取码:8m ...
- JDK11.0.7下载及安装详细教程(win10)
0.背景知识 JRE: Java Runtime Environment JDK:Java Development Kit JRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库. ...
- .NET和.NET Core Web APi FormData多文件上传对比
前言 最近因维护.NET和.NET Core项目用到文件上传功能,虽说也做过,但是没做过什么对比,借此将二者利用Ajax通过FormData上传文件做一个总结,通过视图提交表单太简单,这里不做阐述,希 ...
- Spring Boot 项目几种启动方式
Spring Boot 项目几种启动方式 1. 使用 main 启动 jar xxxx.jar 2. 使用 mvn 启动 mvn spring-boot:run 3. 使用 Spring Boot c ...
- Catalina 默认使用zsh了,你可习惯
zsh 成为默认 shell 淘汰掉我的旧MBP换新后,欢天喜地打开Terminal,感觉有点不对,提示符什么时候变成了 %. 查询了一些资料发现,原来在2019年WWDC期间,苹果推出了macOS ...
- k8s使用需认证的私服仓库
本文内容 在K8s中使用需认证的私服仓库需要导入认证信息到集群中,常规导入方式有两种: 使用Docker已登录的仓库密文导入 使用命令行创建Secret对象导入 本文介绍的就是以上两种方法. 使用Do ...
- Linux根目录下文件夹用途解释
root目录:主要用于存放root用户相关文件的目录: usr目录:安装一个软件时,linux指定的此软件默认安装的目录: home目录:用于存放普通用户的相关文件的目录:例如:我使用adduser ...
- 在虚拟机中安装Mysql
目录 下载Mysql 安装 配置mysql允许远程访问 下载Mysql 下载地址:http://dev.mysql.com/downloads/mysql 我这里下载的是安装版本 安装 配置mysql ...