• luogu P3834 【模板】可持久化线段树 1(主席树)| 静态第k小问题


    题目描述

    如题,给定 nnn 个整数构成的序列,将对于指定的闭区间查询其区间内的第 kkk 小值。

    输入格式

    第一行包含两个正整数 n,mn,mn,m,分别表示序列的长度和查询的个数。

    第二行包含 nnn 个整数,表示这个序列各项的数字。

    接下来 mmm 行每行包含三个整数 l,r,k l, r, kl,r,k , 表示查询区间 [l,r][l, r][l,r] 内的第 kkk 小值。

    输出格式

    输出包含 kkk 行,每行一个整数,依次表示每一次查询的结果


    莫队+树状数组:O(nsqrt(n)logn*logn) 得分:80

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=2e5+10;
    int a[N],b[N],belong[N],n,m;
    inline int read(){
    	int x=0,f=1; char c=getchar();
    	while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); }
    	while('0'<=c&&c<='9'){ x=(x<<3)+(x<<1)+c-48; c=getchar(); }
    	return x*f;
    }
    struct node{
    	int l,r,k,id;
    }e[N];
    inline bool cmp(node t1,node t2){
    	return (belong[t1.l]^belong[t2.l])?t1.l<t2.l:t1.r<t2.r;
    }
    int c[N];
    inline void Add(int x,int y){
    	for(;x<=n;x+=x&(-x))c[x]+=y;
    }
    inline int sum(int x){
    	int ans=0;
    	for(;x;x-=x&(-x))ans+=c[x];
    	return ans;
    }
    inline void add(int x){
    	Add(a[x],1);
    }
    inline void del(int x){
    	Add(a[x],-1);
    }
    inline int check(int mid){
    	return sum(mid);
    }
    inline int erfen(int x){
    	int l=0,r=n,ans=0;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(check(mid)<x){
    			l=mid+1;
    			ans=mid;
    		}else r=mid-1;
    	}
    	return ans+1;
    }
    int ans[N];
    signed main(){
    	n=read(); m=read();
    	int size=sqrt(n);
    	int num=ceil((double)n/size);
    	for(int i=1;i<=num;i++)
    	for(int j=(i-1)*size+1;j<=size*i;j++)
    	belong[j]=i;
    	for(int i=1;i<=n;i++)b[i]=a[i]=read();
    	sort(b+1,b+1+n);
    	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+n,a[i])-b;
    	for(int i=1;i<=m;i++)e[i].l=read(),e[i].r=read(),e[i].k=read(),e[i].id=i;;
    	sort(e+1,e+1+m,cmp);
    	int l=e[1].l,r=e[1].r,k;
    	for(int i=l;i<=r;i++)add(i);
    	for(int i=1;i<=m;i++){
    		while(l<e[i].l)del(l++);
    		while(l>e[i].l)add(--l);
    		while(r<e[i].r)add(++r);
    		while(r>e[i].r)del(r--);
    		k=e[i].k;
    		ans[e[i].id]=erfen(k);
    	}
    	for(int i=1;i<=m;i++)
    	printf("%d
    ",b[ans[i]]);
    }
    
  • 相关阅读:
    【.Net】多语言查看MSDN
    【.Net】 显示星期字符串
    【.Net】 判断时间字符串正确性
    【.Net】 实现窗口拖动
    【.Net】 Winform 单例运行实例
    Kendo 计算字段
    Kendo UI 的 k-template
    UpdatePanel中用后台CS代码调用JS代码,先执行控件事件,后触发JS
    SQL常用
    Node.js 安装
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12124814.html
Copyright © 2020-2023  润新知