luogu 3730
题目背景
will在曼哈顿开了一家交易所,每天,前来买卖股票的人络绎不绝。
现在,will想要了解持股的情况。由于来交♂易的人实在是太多了,需要你写一个程序来帮他完成这个任务。
题目描述
-
前来交易的N个人排成了一行,为了简便起见,每个人都只持有一种股票。
-
不同的的人可能会持有相同的股票。
-
定义一种股票的热度为持有该股票的人数。
- 每次,will会给出这样的询问:在一段连续区间的人之中,热度第k小的股票的热度是多少?
输入输出格式
输入格式:
-
第一行两个正整数N,M,分别表示人数和询问的次数;
-
接下来一行N个正整数,表示每个人所持的股票 a_iai。
- 接下来M行,每行三个正整数l,r,k,表示询问区间[l, r][l,r]中的第k小的热度,保证l\leq 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\n",ans[i]);
return 0;
}



浙公网安备 33010602011771号