zoukankan      html  css  js  c++  java
  • 划分树 poj2104 hdu5249

    KPI

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 616    Accepted Submission(s): 261


    Problem Description
    你工作以后, KPI 就是你的所有了. 我开发了一个服务。取得了非常大的知名度。数十亿的请求被推到一个大管道后同一时候服务从管头拉取请求。让我们来定义每一个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。如今给你服务记录,有时我想知道当前管道内请求的重要值得中间值。
     

    Input
    有大约100组数据。



    每组数据第一行有一个n(1n10000),代表服务记录数。

    接下来有n行。每一行有3种形式
      "in x": 代表重要值为x(0x109)的请求被推进管道。


      "out": 代表服务拉取了管道头部的请求。
      "query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,假设当前管道内有m条请求, 我想知道。升序排序后第floor(m/2)+1th 条请求的重要值.

    为了让题目简单,全部的x都不同。而且假设管道内没有值。就不会有"out"和"query"操作。


     

    Output
    对于每组数据。先输出一行

    Case #i:
    然后每一次"query"。输出当前管道内重要值的中间值。
     

    Sample Input
    6 in 874 query out in 24622 in 12194 query
     

    Sample Output
    Case #1: 874 24622
     
    K-th Number
    Time Limit: 20000MS   Memory Limit: 65536K
    Total Submissions: 41138   Accepted: 13447
    Case Time Limit: 2000MS

    Description

    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

    Hint

    This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

    这两题都 要求子区间的第k大数,假设用快排之后,再查,复杂度太大。不能过,就要用到划分树了,划分树。事实上,就是线段树的

    一个变种了,当然,这样做查询是lg(n)级别,建树是n * lg(n),再加上一次快排,也是n * lg(n),差点儿相同就能够过了!

    先来看看划分树,我们在线段树的基础上,假设每一个结点都保存了。当前子段向左子树走的个数。假设,查询的k要小于,查询段向左走的个数,自然,我们向左子树就能够查到结果。假设,k>向左走的个数,当然要向右找k-midcount个数,区间的变换。我们能够

    推一下向左走就是l + scount, l + ecount - 1。向右走就是mid + 1 + s - l - scount, mid + 1 + e - l - ecount,当中scount就是s之前向左走的个数。 ecount,就是e之前向左走的个数。

    上核心代码

    #define MID(a,b) (((a)+(b))>>1)
    #define N 100050
    int num[20][N], val[20][N];
    //第i层,向左包含自已,向左子树的个数,当前的值
    int pri[N], sorted[N];
    //原始和排序后的数列
    char str[20];
    void build(int l, int r, int layer){
    	if (l >= r){
    		return;
    	}
    	int mid = MID(l, r);
    	int ql = l, qr = mid + 1, leftCount = mid, eqCount = 0;
    	for (int i = l; i <= r; i++)
    		leftCount -= val[layer][i] < sorted[mid];
    	for (int i = l; i <= r; i++){
    		if (i == l){
    			num[layer][i] = 0;
    		}
    		else{
    			num[layer][i] = num[layer][i - 1];
    		}
    		if (val[layer][i] < sorted[mid]){
    			num[layer][i]++;
    			val[layer + 1][ql++] = val[layer][i];
    		}
    		else if (val[layer][i] > sorted[mid]){
    			val[layer + 1][qr++] = val[layer][i];
    		}
    		else {
    			if (eqCount < leftCount){
    				eqCount++;
    				num[layer][i]++;
    				val[layer + 1][ql++] = val[layer][i];
    			}
    			else {
    				val[layer + 1][qr++] = val[layer][i];
    			}
    		}
    	}
    	build(l, mid, layer + 1);
    	build(mid + 1, r, layer + 1);
    }
    //在layer层l到r间,找s-e之间的第k大数
    int query(int l, int r, int layer, int s, int e, int k){
    	if (l >= r || s >= e){
    		return val[layer][s];
    	}
    	int scount, ecount, mid = MID(l, r);
    	if (s == l){
    		scount = 0, ecount = num[layer][e];
    	}
    	else {
    		scount = num[layer][s - 1], ecount = num[layer][e];
    	}
    	int midcount = ecount - scount;
    	if (k <= midcount){
    		return query(l, mid, layer + 1, l + scount, l + ecount - 1, k);
    	}
    	else {
    		return query(mid + 1, r, layer + 1, mid + 1 + s - l - scount, mid + 1 + e - l - ecount, k - midcount);
    	}
    }
    int main()
    {
    	int tcase, tcasenum = 0;
    	int n, k, q, s, e, begin = 1, nn, qcount, m;
    	while (S2(n, m) != EOF)
    	{
    		FI(n){
    			S(val[0][i+1]);
    		}
    		FI(n){
    			sorted[i + 1] = val[0][i + 1];
    		}
    		sort(sorted + 1, sorted + n + 1);
    		build(1, n, 0);
    		FI(m){
    			S2(s, e); S(q);
    			Prn(query(1, n, 0, s,e,q));
    		}
    	}
    	return 0;
    }
    


  • 相关阅读:
    排序数据记录查询
    条件数据记录查询
    简单数据记录查询
    缓冲流
    转换流
    删除数据记录
    更新数据记录
    插入数据记录
    移动前端自适应适配布局解决方案和比较
    如何解决inline-block元素的空白间距
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5239860.html
Copyright © 2011-2022 走看看