luogu 3730

题目背景

will在曼哈顿开了一家交易所,每天,前来买卖股票的人络绎不绝。

现在,will想要了解持股的情况。由于来交♂易的人实在是太多了,需要你写一个程序来帮他完成这个任务。

题目描述

  • 前来交易的N个人排成了一行,为了简便起见,每个人都只持有一种股票。

  • 不同的的人可能会持有相同的股票。

  • 定义一种股票的热度为持有该股票的人数。

  • 每次,will会给出这样的询问:在一段连续区间的人之中,热度第k小的股票的热度是多少?

输入输出格式

输入格式:

 

  • 第一行两个正整数N,M,分别表示人数和询问的次数;

  • 接下来一行N个正整数,表示每个人所持的股票 a_iai

  • 接下来M行,每行三个正整数l,r,k,表示询问区间[l, r][l,r]中的第k小的热度,保证lleq rlr。

 

输出格式:

 

  • 对于每个询问,输出一行一个数,表示区间[l, r]中的第k小的热度值。

  • 如果k大于区间里股票的种类数,输出-1。

 

输入输出样例

输入样例#1: 复制
4 4  
2 3 3 3  
1 4 1  
1 4 2  
1 3 2
1 3 3
输出样例#1: 复制
1  
3  
2  
-1

说明

对于20%的数据,N,M1000;

对于另外10%的数据,所有的l=1,r=N;

对于100%的数据,N,M100000,ai109;

链接: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;
} 

  

原文地址:https://www.cnblogs.com/Stump/p/7811791.html