题目背景
will在曼哈顿开了一家交易所,每天,前来买卖股票的人络绎不绝。
现在,will想要了解持股的情况。由于来交♂易的人实在是太多了,需要你写一个程序来帮他完成这个任务。
题目描述
-
前来交易的N个人排成了一行,为了简便起见,每个人都只持有一种股票。
-
不同的的人可能会持有相同的股票。
-
定义一种股票的热度为持有该股票的人数。
- 每次,will会给出这样的询问:在一段连续区间的人之中,热度第k小的股票的热度是多少?
输入输出格式
输入格式:
-
第一行两个正整数N,M,分别表示人数和询问的次数;
-
接下来一行N个正整数,表示每个人所持的股票 a_iai。
- 接下来M行,每行三个正整数l,r,k,表示询问区间[l, r][l,r]中的第k小的热度,保证lleq rl≤r。
输出格式:
-
对于每个询问,输出一行一个数,表示区间[l, r]中的第k小的热度值。
- 如果k大于区间里股票的种类数,输出-1。
输入输出样例
说明
对于20%的数据,N,M≤1000;
对于另外10%的数据,所有的l=1,r=N;
对于100%的数据,N,M≤100000,ai≤109;
链接:https://www.luogu.org/problemnew/show/3730
赛前,来一波暴力分块大法好啊
莫队算法套分块查询.
对于n个数离散化后,它们的值域在[1,n]
考虑如果题目问的是区间众数查询.
那么,这就是莫队入门经典题.
我们会对每个数的出现次数的个数放入一个新数组维护,并进行统计
那么,我们可以对这新数组分块进行维护,分成(√n)块.
莫队算法进行移动时,对于单点进行修改,所在的块的信息也进行修改
对于询问时先在块上暴力跳,直到不能跳为止,再在点上跳.
这样复杂度为O(n√n).
AC代码:
#include<stdio.h> #include<iostream> #include<math.h> #include<algorithm> #define BIG 200011 #define FOR(i,s,t) for(register int i=s;i<=t;++i) using std::sort; using std::unique; using std::lower_bound; int hv[BIG],f[BIG],a[BIG],b[BIG],ans[BIG],bl[BIG],sum[BIG]; int n,m,blo,cnt; class node{ public: int l,r,k,bs; inline bool operator<(node A)const{ if(bl[l]!=bl[A.l])return bl[l]<bl[A.l]; if(bl[r]!=bl[A.r])return bl[r]<bl[A.r]; return k<A.k; } }q[BIG]; int l,r,p; inline void update(int pos,int w){ --sum[bl[hv[a[pos]]]]; --f[hv[a[pos]]]; w?++hv[a[pos]]:--hv[a[pos]]; ++sum[bl[hv[a[pos]]]]; ++f[hv[a[pos]]]; } inline int query(int k){ register int i; for(i=1;i<=blo;++i) if(k-sum[i]>0) k-=sum[i]; else break; for(register int j=(i-1)*blo+1;j<=i*blo;++j){ k-=f[j]; if(k<=0) return j; } return -1; } int main(){ scanf("%d%d",&n,&m); blo=sqrt(n); FOR(i,1,n)bl[i]=(i-1)/blo+1; FOR(i,1,n)scanf("%d",a+i),b[i]=a[i]; sort(b+1,b+n+1); cnt=unique(b+1,b+n+1)-b-1; FOR(i,1,n)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b; FOR(i,1,m)scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k),q[i].bs=i; sort(q+1,q+m+1); l=1,r=0; FOR(i,1,m){ while(l<q[i].l)update(l++,0); while(q[i].l<l)update(--l,1); while(r<q[i].r)update(++r,1); while(q[i].r<r)update(r--,0); ans[q[i].bs]=query(q[i].k); } FOR(i,1,m)printf("%d ",ans[i]); return 0; }