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的数数(数状数组)的更多相关文章

  1. hdoj 1166 敌兵布阵 线段数和树状数组

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  2. SCAU-1144 数星星-HDU-1166-树状数组的应用

    本文借鉴代码提供:https://www.cnblogs.com/geek1116/p/5566709.html树状数组详解:https://www.cnblogs.com/xenny/p/97396 ...

  3. BZOJ 2120 数颜色(树状数组套主席树)

    1A啊,激动. 首先,不修改的情况下可以直接用主席树搞,修改的话,直接用主席树搞一次修改的情况下复杂度是O(nlogn)的. 就像你要求区间和一样,用前缀和查询是O(1),修改是O(n),只不过主席树 ...

  4. 树状数组求逆序对:POJ 2299、3067

    前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换 ...

  5. FZU 2029 买票问题 树状数组+STL

    题目链接:买票问题 思路:优先队列维护忍耐度最低的人在队首,leave操作ok. vis数组记录从1到n的编号的人们是不是在队列中,top维护队首的人的编号.pop操作搞定. 然后,check操作就是 ...

  6. HDU 5775 树状数组

    Bubble Sort Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. Ping pong(树状数组经典)

    Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  8. poj2299树状数组入门,求逆序对

    今天入门了树状数组 习题链接 https://blog.csdn.net/liuqiyao_01/article/details/26963913 离散化数据:用一个数组来记录每个值在数列中的排名,不 ...

  9. 【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组

    题目描述 给出两个长度分别为n.m的序列A.B,求出B的所有长度为n的连续子序列(子串),满足:序列中第i小的数在序列的Ai位置. 输入 第一行包含两个整数n, m (2≤n≤m≤1000000).  ...

  10. Codeforces Round #401 (Div. 1) C(set+树状数组)

    题意: 给出一个序列,给出一个k,要求给出一个划分方案,使得连续区间内不同的数不超过k个,问划分的最少区间个数,输出时将k=1~n的答案都输出 比赛的时候想的有点偏,然后写了个nlog^2n的做法,T ...

随机推荐

  1. Android Studio简单的登陆界面

    在app->src->main->java里面找到MainActivity.java,将鼠标放到activity-main上按住Ctrl后单击跳转到activity-main.xml ...

  2. MySQL时间设计 int timestamp datatime 查询效率性能比较

    在数据库设计的时候,我们经常会需要设计时间字段,在MYSQL中,时间字段可以使用int.timestamp.datetime三种类型来存储,那么这三种类型哪一种用来存储时间性能比较高,效率好呢?飘易就 ...

  3. 11、Java 日期时间 日期工具类

    一.简介 在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题.故此,Java8引入了一套全新的日期时间处理 ...

  4. Linux 安装 PostgreSQL

    Linux 安装 PostgreSQL CentOS 7 安装 PostgreSQL 10 步骤 官网安装步骤,选择服务器和数据库版本,会给出相应的安装命令 # 安装 yum install -y h ...

  5. CentOS7安装MinIO教程,并在C#客户端WPF中实现监控上传进度

    MinIO的详细介绍可以参考官网(https://min.io/product/overview). 简单来说它是一个实现了AWS S3标准的100%开源的,可商用的( Apache V2 licen ...

  6. 聊聊Java内省Introspector

    前提 这篇文章主要分析一下Introspector(内省,应该读xing第三声,没有找到很好的翻译,下文暂且这样称呼)的用法.Introspector是一个专门处理JavaBean的工具类,用来获取J ...

  7. Java并发-Synchronized关键字

    一.多线程下的i++操作的并发问题 package passtra; public class SynchronizedDemo implements Runnable{ private static ...

  8. 阿里P8架构师大话设计模式,体会乐与怒的程序人生中值得回味一幕

    本书特色 本书有两个特色,第一特色是重视过程.看了太多的计算机编程类的图书,大多数书籍都是集中在讲授优秀的解决方案或者一个完美的程序样例,但对这些解决方案和程序的演变过程却重视不够,好书之所以好,就是 ...

  9. 30分钟闲置服务器建站(gitlab为例)

    前言 最近博主的阿里云主机又到了续费的时候了,刚买云主机的时候那是各种优惠各种打折,续费的时候只能当孙子了. 为了节省开支,又保证高性能的前提下,买了台10代NUC,内存和ssd自选,搭建一台个人服务 ...

  10. sql server 查询表字段的说明备注信息

    SELECT 表名 = case when a.colorder= then d.name else '' end, 表说明 = case when a.colorder= then isnull(f ...