zoukankan      html  css  js  c++  java
  • POJ 2104 K-th Number

    http://poj.org/problem?id=2104

    题目

    Time Limit:2s

    You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.

    That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?"

    For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

    Input

    The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).

    The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.

    The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

    Output

    For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

    Sample Input

    7 3
    1 5 2 6 3 7 4
    2 5 3
    4 4 1
    1 7 3
    

    Sample Output

    5
    6
    3
    

    题解

    求第k大的数可以直接排序$mathcal{O}(nlog n)$,或者修改一下快速排序的方法,做到$mathcal{O}(n)$,对于多组询问就没办法了,只能$mathcal{O}(nm)$显然超时

    可以从值域入手,统计小于等于x的数有多少个,如果结果(ans)小于等于k,说明这个数小于等于x(可能等于x的数字不存在,导致个数没有变化),否则大于x,那么就可以进行二分,继续在左半边值域或右半边值域继续,需要注意的是如果在右半边,需要把$k-=ans$

    对于多个询问,可以把在左半边值域的询问递归进左半边,右半边值域的询问递归进右半边

    因为范围不同,可以用树状树组保存小于等于x的数字的位置,前缀和表示这前面有多少个小于等于x的数字,减去(左边界-1)的值就是这个区间小于等于x的数字的个数

    由于数字很多,需要使用读写挂= =https://www.luogu.com.cn/blog/encore/io-you-hua-nei-suo-shi

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    using namespace std;
    char buf[1<<21], *p1=buf, *p2=buf; bool beof;
    #define gc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin)),(p1==p2)?EOF:*p1++)
    template<class T> inline void read(T &x) {
    	x=0; char ch; int si=1;
    	do ch=getchar(); while(!isdigit(ch) && ch!='-');
    	if(ch=='-') si=-1,ch=getchar();
    	while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} x*=si;
    }
    #define MAXN 100007
    #define MAXM 5007
    #define MAXV 1000000000
    struct node {
    	int v, l, r, id;
    } op[MAXN+MAXM], tl[MAXN+MAXM], tr[MAXN+MAXM];
    int opn;
    int ans[MAXM];
    int bt[MAXN];
    int n, m;
    inline void opa(int x,int v) {
    	for(;x<=n;x+=x&-x) {
    		bt[x]+=v;
    	}
    }
    inline int opq(int x) {
    	int ans=0;
    	for(;x>0;x-=x&-x) {
    		ans+=bt[x];
    	}
    	return ans;
    }
    void calc(int l, int r, int ql, int qr) {
    	if(l==r) {
    		REP(i,ql,qr) if(op[i].v) {
    			ans[op[i].id]=l;
    		}
    		return;
    	}
    	int m=(l+r)>>1;
    	int nl=0,nr=0; bool ll=false, rr=false;
    	REP(i,ql,qr) {
    		if(op[i].v==0) {
    			if(op[i].r<=m) opa(op[i].l,1),tl[nl++]=op[i];
    			else tr[nr++]=op[i];
    		} else {
    			int ans=opq(op[i].r)-opq(op[i].l-1);
    			if(op[i].v<=ans) tl[nl++]=op[i],ll=true;
    			else {
    				tr[nr]=op[i],rr=true;
    				tr[nr].v-=ans;
    				nr++;
    			}
    		}
    	}
    	REP(i,0,nl) if(tl[i].v==0) {
    		opa(tl[i].l,-1);
    	}
    	opn=ql;
    	REP(i,0,nl) op[opn++]=tl[i];
    	REP(i,0,nr) op[opn++]=tr[i];
    	if(ll) calc(l,m,ql,ql+nl);
    	if(rr) calc(m+1,r,ql+nl,qr);
    }
    int main() {
    	read(n); read(m); memset(bt,0,sizeof(int)*(n+1));
    	opn=0;
    	REPE(i,1,n) {
    		op[opn].v=0, op[opn].l=i;
    		read(op[opn].r);
    		opn++;
    	}
    	REP(i,0,m) {
    		read(op[opn].l); read(op[opn].r); read(op[opn].v); op[opn].id=i;
    		opn++;
    	}
    	calc(-MAXV,MAXV,0,opn);
    	REP(i,0,m) printf("%d
    ", ans[i]);
    }
    
  • 相关阅读:
    Elasticsearch常用插件集合(转)
    istio 安装与bookinfo示例运行(转)
    kubernetes发布tomcat服务,通过deployment,service布署(转)
    记一次ceph集群的严重故障 (转)
    Linux centos 7 安装NFS服务
    Centos7下使用Ceph-deploy快速部署Ceph分布式存储-操作记录(转)
    docker 安装 jmeter
    idea 2018.1破解激活方法,有效期至2099年
    MySQL和Oracle的区别
    SpringCloud面试题
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12271390.html
Copyright © 2011-2022 走看看