• #6273. 郁金香 题解


    题目链接:#6273. 郁金香

    题目大意:给定一个长度为 (n) 序列 ({a_i}_{i=1}^{n})(m) 次询问区间 ([l,r]) 中出现次数第 (k) 多的数,如出现次数相同,则令数较小出现次数较多。
    (n,m,a_ileq 10^5)


    题解:听说有划分树的 ( ext{polylog}) 做法,可惜我并不会。<-- 不要听博主这个弱智的话,这问题严格强于区间众数。

    直接莫队,令块长为 (S) ,那么我们考虑将值域分块,这样的话可以在 (O(S+frac{n}{S})) 的时间内求出出现次数。

    接下来考虑求出现次数为 (x) 的第 (k) 小值,所以我们直接对序列分块,令 (f_{i,j}) 表示出现次数为 (i) 的数在第 (j) 块中的个数,容易发现可以在 (O(S+frac{n}{S})) 的时间内解决。

    (S=sqrt{n}) 时最优,时间复杂度为 (O(qsqrt{n}))

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int Maxv=100000;
    const int Maxn=100000;
    const int Maxs=334;
    const int Maxb=(Maxn-1)/Maxs+1;
    int n,m;
    struct Question{
    	int l,r,k;
    	int id;
    	friend bool operator <(Question a,Question b){
    		if((a.l-1)/Maxs==(b.l-1)/Maxs){
    			if(((a.l-1)/Maxs)&1){
    				return a.r>b.r;
    			}
    			return a.r<b.r;
    		}
    		return a.l<b.l;
    	}
    }qu[Maxn+5];
    int a[Maxn+5];
    int f[Maxv+5][Maxb+5];
    int cnt[Maxn+5];
    int sum[Maxn+5],s_block[Maxb+5];
    int ans[Maxn+5];
    void add(int x,int a){
    	int last=cnt[x];
    	cnt[x]+=a;
    	f[last][(x-1)/Maxs+1]--;
    	f[cnt[x]][(x-1)/Maxs+1]++;
    	if(last){
    		s_block[(last-1)/Maxs+1]--;
    	}
    	else{
    		s_block[0]--;
    	}
    	if(cnt[x]){
    		s_block[(cnt[x]-1)/Maxs+1]++;
    	}
    	else{
    		s_block[0]++;
    	}
    	sum[last]--;
    	sum[cnt[x]]++;
    }
    int query(int k){
    	int bel;
    	for(bel=(n-1)/Maxs+1;k>s_block[bel]&&bel;bel--){
    		k-=s_block[bel];
    	}
    	int num;
    	for(num=min(n,bel*Maxs);k>sum[num];num--){
    		k-=sum[num];
    	}
    	for(bel=1;k>f[num][bel];bel++){
    		k-=f[num][bel];
    	}
    	int pos;
    	for(pos=(bel-1)*Maxs+1;k>(cnt[pos]==num);pos++){
    		k-=(cnt[pos]==num);
    	}
    	return pos;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	scanf("%d",&m);
    	sum[0]=s_block[0]=n;
    	for(int i=1;i<=n;i++){
    		f[0][(a[i]-1)/Maxs+1]++;
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d",&qu[i].l,&qu[i].r,&qu[i].k);
    		qu[i].id=i;
    	}
    	sort(qu+1,qu+1+m);
    	int pos_l=1,pos_r=0;
    	for(int i=1;i<=m;i++){
    		if(qu[i].k>n){
    			ans[qu[i].id]=-1;
    			continue;
    		}
    		while(pos_r<qu[i].r){
    			pos_r++;
    			add(a[pos_r],1);
    		}
    		while(pos_l>qu[i].l){
    			pos_l--;
    			add(a[pos_l],1);
    		}
    		while(pos_r>qu[i].r){
    			add(a[pos_r],-1);
    			pos_r--;
    		}
    		while(pos_l<qu[i].l){
    			add(a[pos_l],-1);
    			pos_l++;
    		}
    		ans[qu[i].id]=query(qu[i].k);
    		if(cnt[ans[qu[i].id]]==0){
    			ans[qu[i].id]=-1;
    		}
    	}
    	for(int i=1;i<=m;i++){
    		if(ans[i]==-1){
    			puts("0");
    		}
    		else{
    			printf("%d
    ",ans[i]);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    write(byte[] b, int off, int len)
    getAttribute 与getParmeter 区别
    ServletContext
    SercletConfig 详解
    MYSQL导入数据出现ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
    mybatis在xml文件中处理大于号小于号的方法
    阿里云实名认证接口调试
    js encodeuricomponent base64
    Introspector内存溢出的原理解析
    JVM虚拟机工作原理
  • 原文地址:https://www.cnblogs.com/withhope/p/13930797.html
Copyright © 2020-2023  润新知