zoukankan      html  css  js  c++  java
  • HDU5107---K-short Problem (线段树区间 合并、第k大)

    题意:二维平面上 N 个高度为 Hi 建筑物,M次询问,每次询问输出 位于坐标(x ,y)左下角(也就是xi <= x && yi <= y)的建筑物中的第k高的建筑物的高度,如果不存在输出-1.

    思路:可以发现k很小,最大才是10。对于区间第k大的问题,如果k很小的话,线段树也是可以的,,当然这里要用到 区间合并,对于每个节点 记录其 孩子中 前2*k个高度(不一定非要2*k,只要大于k就可以,至于为什么,自己可以想想),进行合并排序。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 const int maxn = 3e4+10;
      8 struct Building
      9 {
     10     int x,y,flag,k,idx;
     11     Building (){}
     12     Building (int _x,int _y,int _z): x(_x),y(_y),k(_z){}
     13     bool operator < (const Building &rhs)const
     14     {
     15         return x < rhs.x || (x == rhs.x && y < rhs.y) ||
     16         (x == rhs.x && y == rhs.y && flag < rhs.flag);
     17     }
     18 }bui[maxn<<1];
     19 struct Seg_tree
     20 {
     21     int sum,num[25];
     22     Seg_tree (){sum = 0;}
     23 }seg[maxn<<3];              //正常来说4倍就够了,可是这题不是maxn而是2*maxn,所以要(2*maxn)*4倍
     24 int vec[maxn*2],ans[maxn*2];
     25 void build (int l,int r,int pos)
     26 {
     27     seg[pos].sum = 0;
     28     if (l == r)
     29         return;
     30     int mid = (l + r) >> 1;
     31     build(l,mid,pos<<1);
     32     build(mid+1,r,pos<<1|1);
     33 }
     34 void _sort(int pos)
     35 {
     36     sort(seg[pos].num,seg[pos].num+seg[pos].sum);
     37     seg[pos].sum = min(10,seg[pos].sum);
     38 }
     39 void push_up(int pos)
     40 {
     41     int tot = 0;
     42     for (int i = 0; i < seg[pos<<1].sum; i++)
     43         seg[pos].num[tot++] = seg[pos<<1].num[i];
     44     for (int i = 0; i < seg[pos<<1|1].sum; i++)
     45         seg[pos].num[tot++] = seg[pos<<1|1].num[i];
     46     seg[pos].sum = tot;
     47     _sort(pos);
     48 }
     49 void update(int l,int r,int pos,int p,int val)
     50 {
     51     if (l == r)
     52     {
     53         seg[pos].num[seg[pos].sum++] = val;
     54         _sort(pos);                                            //对当前节点内的高度进行排序
     55         return;
     56     }
     57     int mid = (l + r) >> 1;
     58     if (p <= mid)
     59         update(l,mid,pos<<1,p,val);
     60     else
     61         update(mid+1,r,pos<<1|1,p,val);
     62     push_up(pos);                                              //左右孩子合并 取出前10个高度
     63 }
     64 int pre_ans[25],siz;
     65 void query(int l,int r,int pos,int ua,int ub)
     66 {
     67     if (ua <= l && ub >= r)
     68     {
     69         for (int i = 0; i < seg[pos].sum; i++)
     70             pre_ans[siz++] = seg[pos].num[i];
     71         sort(pre_ans,pre_ans+siz);
     72         siz = min(10,siz);
     73         return;
     74     }
     75     int mid = (l + r) >> 1;
     76     if (ua <= mid)
     77         query (l,mid,pos<<1,ua,ub);
     78     if (ub > mid)
     79         query (mid+1,r,pos<<1|1,ua,ub);
     80 }
     81 int main(void)
     82 {
     83     #ifndef ONLINE_JUDGE
     84         freopen("in.txt","r",stdin);
     85     #endif
     86     int n,m;
     87     while (~scanf ("%d%d",&n,&m))
     88     {
     89         int tot = 0;
     90         for (int i = 0; i < n + m ; i++)
     91         {
     92             int u,v,c;
     93             scanf ("%d%d%d",&u,&v,&c);
     94             bui[i] = Building (u,v,c);
     95             if (i < n)
     96                 bui[i].flag = 0;
     97             else
     98                 bui[i].flag = 1;
     99             vec[tot++] = v;
    100             bui[i].idx = i;
    101         }
    102         sort(vec,vec+tot);
    103         sort(bui,bui+n+m);
    104         tot = unique(vec, vec + tot) - vec;
    105         build(1,tot,1);
    106         for (int i = 0; i < n + m; i++)
    107         {
    108             int p = 1 + lower_bound(vec,vec+tot,bui[i].y) - vec;
    109             if (bui[i].flag == 0)
    110                 update(1,tot,1,p,bui[i].k);
    111             else
    112             {
    113                 siz = 0;
    114                 query(1,tot,1,1,p);
    115                 if (bui[i].k > siz)
    116                     ans[bui[i].idx] = -1;
    117                 else
    118                     ans[bui[i].idx] = pre_ans[bui[i].k-1];
    119             }
    120         }
    121         for (int i = n; i < n + m; i++)
    122             printf("%d
    ",ans[i]);
    123     }
    124     return 0;
    125 }
  • 相关阅读:
    PHP延迟静态绑定
    PHP SPL神器实现堆排序
    魔术方法__sleep 和 __wakeup
    SPL 笔记
    PHP中对象的深拷贝与浅拷贝
    PHP的垃圾回收机制详解
    深入理解PHP中赋值与引用
    xdebug安装及使用小结
    工作中碰到的一个问题(cookie相关)
    分享一个解析XML成为php数组的方法
  • 原文地址:https://www.cnblogs.com/oneshot/p/4115487.html
Copyright © 2011-2022 走看看