zoukankan      html  css  js  c++  java
  • 18.10.22 POJ 2104 K-th Number(二分+线段树+离散化)

    描述

    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.输入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).输出For each question output the answer to it --- the k-th number in sorted a[i...j] segment

    .样例输入

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

    样例输出

    5
    6
    3

    提示

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

    来源

    Northeastern Europe 2004, Northern Subregion

      1 #include <iostream>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <stack>
      5 #include <string>
      6 #include <math.h>
      7 #include <queue>
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <vector>
     11 #include <fstream>
     12 #include <set>
     13 #include<map>
     14 #define l(rt) rt*2
     15 #define r(rt) rt*2+1
     16 #define mid(l,r) (l+r)/2
     17 
     18 using namespace std;
     19 const int maxn = 100005;
     20 int n, m,num[maxn],b[maxn];
     21 struct number {
     22     int val, id;
     23     bool operator <(number a) {
     24         return val < a.val;
     25     }
     26 };
     27 number _num[maxn];
     28 struct node {
     29     vector<int> va;
     30     int l, r;
     31 }tree[4*maxn];
     32 
     33 void build(int rt,int l,int r) {
     34     tree[rt].l = l, tree[rt].r = r;
     35     if (l == r)
     36     {
     37         tree[rt].va.push_back(b[l]);
     38         return;
     39     }
     40     build(l(rt), l, mid(l, r));
     41     build(r(rt), mid(l, r) + 1, r);
     42     int i = 0, j = 0, sizer = tree[r(rt)].va.size(), sizel = tree[l(rt)].va.size();
     43     while (i != sizel || j != sizer) {
     44         if (i != sizel && j != sizer) {
     45             if (tree[l(rt)].va[i] <= tree[r(rt)].va[j])
     46                 tree[rt].va.push_back(tree[l(rt)].va[i++]);
     47             else
     48                 tree[rt].va.push_back(tree[r(rt)].va[j++]);
     49         }
     50         if (i == sizel)
     51             while (j != sizer)
     52                 tree[rt].va.push_back(tree[r(rt)].va[j++]);
     53         if (j == sizer)
     54             while (i != sizel)
     55                 tree[rt].va.push_back(tree[l(rt)].va[i++]);
     56     }
     57     return;
     58 }
     59 
     60 int query(int rt, int l, int r, int x) {//小于等于x的个数
     61     if (tree[rt].l == l && tree[rt].r == r)
     62         return upper_bound(tree[rt].va.begin(), tree[rt].va.end(), x)-tree[rt].va.begin();
     63     int midn = mid(tree[rt].r, tree[rt].l);
     64     if (l > midn)
     65         return query(r(rt), l, r, x);
     66     else if (r <= midn)
     67         return query(l(rt), l, r, x);
     68     else
     69         return query(l(rt), l, midn, x) + query(r(rt), midn + 1, r, x);
     70 }
     71 
     72 void solve(int l, int r, int k) {
     73     int res;
     74     int s = 1, e = n+1;
     75     while (s<e) {
     76         int x = s + (e - s) / 2;
     77         res = query(1, l, r, x);
     78         if (res >= k)e = x;
     79         else
     80             s = x + 1;
     81     }
     82     printf("%d
    ", num[s]);
     83 }
     84 
     85 void init() {
     86     scanf("%d%d", &n, &m);
     87     for (int i = 1; i <= n; i++)
     88     {
     89         scanf("%d", &num[i]);
     90         _num[i].val = num[i];
     91         _num[i].id = i;
     92     }
     93     sort(_num + 1, _num + n + 1);
     94     for (int i = 1; i <= n; i++) 
     95         b[_num[i].id] = i;
     96     build(1,1, n);
     97     sort(num + 1, num + n + 1);
     98     while (m--) {
     99         int x, y, k;
    100         scanf("%d%d%d", &x, &y, &k);
    101         solve(x, y, k);
    102     }
    103 }
    104 
    105 int main()
    106 {
    107     init();
    108     return 0;
    109 }
    View Code

    每个星期一都是意识模糊的一天

    查了下,还有一种做法是主席树,很有意思,准备之后看一下

    思路:

    二分查找答案使得尝试的这个数x在所考察区间内,正好有k个数字小于等于它

    线段树的作用是得到区间内小于等于x的数的个数

    离散化是加快速度

    这个实现超烂,又臭又长

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    查看linux文件目录的大小和文件夹包含的文件数
    linux下oracle 基本操作
    中宇 设备证书 导入配置
    as5 samba 图形配置
    QQ用户免费申领新型电子密码卡
    GRUB引导下进Linux单用户模式的三种方式
    Iptables 规则 一些简单实例和详细介绍
    Linux上JDK的 安装和卸载 详细 (转)
    Linux/Unix命令之Ethtool (设置千兆网卡速度及模式)
    oracle 下 创建数据库和用户界面操作 和sql 语句 下的创建方法
  • 原文地址:https://www.cnblogs.com/yalphait/p/9832427.html
Copyright © 2011-2022 走看看