zoukankan      html  css  js  c++  java
  • 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;
    } 
    

      

  • 相关阅读:
    关于vue中如何实现排到他思想
    js 文件下载
    js文件上传
    webpack学习笔记
    this总结
    React中props与state
    js事件总结
    js深拷贝与浅拷贝
    JS设计模式之观察者模式
    ES5与ES6的继承
  • 原文地址:https://www.cnblogs.com/Stump/p/7811791.html
Copyright © 2011-2022 走看看