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

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

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 3e4+;
struct Building
{
int x,y,flag,k,idx;
Building (){}
Building (int _x,int _y,int _z): x(_x),y(_y),k(_z){}
bool operator < (const Building &rhs)const
{
return x < rhs.x || (x == rhs.x && y < rhs.y) ||
(x == rhs.x && y == rhs.y && flag < rhs.flag);
}
}bui[maxn<<];
struct Seg_tree
{
int sum,num[];
Seg_tree (){sum = ;}
}seg[maxn<<]; //正常来说4倍就够了,可是这题不是maxn而是2*maxn,所以要(2*maxn)*4倍
int vec[maxn*],ans[maxn*];
void build (int l,int r,int pos)
{
seg[pos].sum = ;
if (l == r)
return;
int mid = (l + r) >> ;
build(l,mid,pos<<);
build(mid+,r,pos<<|);
}
void _sort(int pos)
{
sort(seg[pos].num,seg[pos].num+seg[pos].sum);
seg[pos].sum = min(,seg[pos].sum);
}
void push_up(int pos)
{
int tot = ;
for (int i = ; i < seg[pos<<].sum; i++)
seg[pos].num[tot++] = seg[pos<<].num[i];
for (int i = ; i < seg[pos<<|].sum; i++)
seg[pos].num[tot++] = seg[pos<<|].num[i];
seg[pos].sum = tot;
_sort(pos);
}
void update(int l,int r,int pos,int p,int val)
{
if (l == r)
{
seg[pos].num[seg[pos].sum++] = val;
_sort(pos); //对当前节点内的高度进行排序
return;
}
int mid = (l + r) >> ;
if (p <= mid)
update(l,mid,pos<<,p,val);
else
update(mid+,r,pos<<|,p,val);
push_up(pos); //左右孩子合并 取出前10个高度
}
int pre_ans[],siz;
void query(int l,int r,int pos,int ua,int ub)
{
if (ua <= l && ub >= r)
{
for (int i = ; i < seg[pos].sum; i++)
pre_ans[siz++] = seg[pos].num[i];
sort(pre_ans,pre_ans+siz);
siz = min(,siz);
return;
}
int mid = (l + r) >> ;
if (ua <= mid)
query (l,mid,pos<<,ua,ub);
if (ub > mid)
query (mid+,r,pos<<|,ua,ub);
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,m;
while (~scanf ("%d%d",&n,&m))
{
int tot = ;
for (int i = ; i < n + m ; i++)
{
int u,v,c;
scanf ("%d%d%d",&u,&v,&c);
bui[i] = Building (u,v,c);
if (i < n)
bui[i].flag = ;
else
bui[i].flag = ;
vec[tot++] = v;
bui[i].idx = i;
}
sort(vec,vec+tot);
sort(bui,bui+n+m);
tot = unique(vec, vec + tot) - vec;
build(,tot,);
for (int i = ; i < n + m; i++)
{
int p = + lower_bound(vec,vec+tot,bui[i].y) - vec;
if (bui[i].flag == )
update(,tot,,p,bui[i].k);
else
{
siz = ;
query(,tot,,,p);
if (bui[i].k > siz)
ans[bui[i].idx] = -;
else
ans[bui[i].idx] = pre_ans[bui[i].k-];
}
}
for (int i = n; i < n + m; i++)
printf("%d\n",ans[i]);
}
return ;
}

HDU5107---K-short Problem (线段树区间 合并、第k大)的更多相关文章

  1. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  2. hdu-3308 LCIS (线段树区间合并)

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  3. hdu 3308(线段树区间合并)

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  4. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  5. hdu3911 线段树 区间合并

    //Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  6. 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并

    题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...

  7. 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)

    [BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...

  8. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  9. HDU 3308 (线段树区间合并)

    http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意: 两个操作  : 1 修改 单点  a 处的值. 2 求出 区间[a,b]内的最长上升子序列. 做法 ...

  10. LCIS HDU - 3308 (线段树区间合并)

    LCIS HDU - 3308 Given n integers. You have two operations: U A B: replace the Ath number by B. (inde ...

随机推荐

  1. Python标准库:内置函数bytearray([source[, encoding[, errors]]])

    返回一个新字节数组.这个数组里的元素是可变的.而且每一个元素的值范围: 0 <= x < 256.能够通过"字节与字节数组操作"章节来查看相关字节数组的内容.以下说明一 ...

  2. [AngularJS] angular-md-table for Angular material design

    Download from npm:https://www.npmjs.com/package/angular-md-table +: Responsive: Has both Mobile view ...

  3. C语言判断文件是否存在

      用函数access,头文件是io.h,原型:    int   access(const   char   *filename,   int   amode); amode参数为0时表示检查文件的 ...

  4. STL中的find_if函数

      上一篇文章也讲过,find()函数只能处理简单类型的内容,也就是缺省类型,如果你想用一个自定义类型的数据作为查找依据则会出错!这里将讲述另外一个函数find_if()的用法 这是find()的一个 ...

  5. Android - Service启动机制

      以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luoshe ...

  6. MyEclipse设置默认的文档注释

  7. CSS 之 margin知识点

    1.margin的百分比值 普通元素的百分比maigin相对于容器元素的宽度(width) 进行计算的. 这里我们在图片外面设置一个宽高分别为800 * 600的容器.设置img{ margin: 1 ...

  8. html5的Canvas

    Canvas一般是指画布,最近对用html5写游戏比较感兴趣,所以简单的用了一下Canvas. 之前接触Canvas是在silverlight和wpf上用到过他,在silverlight上Canvas ...

  9. ExtJS实例1

    1.创建一个Extjs的Window,用ajax请求HTML文件,并执行HTML的代码和脚本 窗体中文字是从一个HTML中获取,并且HTML中执行脚本使窗体高亮1秒 主页面: <!DOCTYPE ...

  10. 传输层-UDP

    传输层构建在网络层之上,传输层提供端口到端口之间的通讯. 传输层通过端口号来标识一个端口,不同于网卡,端口是逻辑上的概念.传输层的端口为16个比特(bit)长度,即最多能表示65 536个端口,端口号 ...