G - Queue

HDU - 5493

题目大意:给你n个人的身高和这个人前面或者后面有多少个比他高的人,让你还原这个序列,按字典序输出。

题解:

首先按高度排序。

设每个人在其前面有k个人,设比这个人高有x个人,所以k=min(k,x-k),求出每一个人在他前面比他高的人的数量。

然后用线段树来维护一段区间的空位,因为对于每一个人来说比他高的人肯定都是出现在他后面,所以这个就说明它前面要空出几个空位。

但是线段树可以维护一段区间的空位,没办法准确找出我需要空位为一个准确的数的位置。

这个就可以二分答案。

要注意几个细节,如果用线段树的话,这个 l 不要从1开始,不然会 T,

然后就是二分这个地方要注意写法,我之前一种写法错了。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
int ans[maxn];
int n;
struct node {
int h, k;
node(int h = , int k = ) :h(h), k(k) {}
}ex[maxn]; bool cmp(node a, node b) {
return a.h < b.h;
}
int sum[maxn * ];
void push_up(int id) {
sum[id] = sum[id << ] + sum[id << | ];
} void build(int id, int l, int r) {
sum[id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void update(int id, int l, int r, int pos) {
if (l == r) {
sum[id] = ;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , l, mid, pos);
else update(id << | , mid + , r, pos);
push_up(id);
} int query(int id, int l, int r, int x, int y) {
if (x <= l && y >= r) return r - l + - sum[id];
int mid = (l + r) >> ;
int ans = ;
if (x <= mid) ans += query(id << , l, mid, x, y);
if (y > mid) ans += query(id << | , mid + , r, x, y);
return ans;
} int main() {
int t, cnt = ;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
int h, k;
scanf("%d%d", &h, &k);
ex[i] = node(h, k);
}
int flag = ;
sort(ex + , ex + + n, cmp);
for (int i = ; i <= n; i++) {
if (n - i - ex[i].k < ) flag = ;
ex[i].k = min(ex[i].k, n - i - ex[i].k);
}
if (flag) {
printf("Case #%d: impossible\n", ++cnt);
continue;
}
build(, , n);
for (int i = ; i <= n; i++) {
int l = ex[i].k + , r = n;
while (l <= r) {
int mid = (l + r) >> ;
int res = query(, , n, , mid);
if (res > ex[i].k) r = mid - ;
else l = mid + ;
}
ans[r + ] = ex[i].h;
update(, , n, r + );
}
printf("Case #%d:", ++cnt);
for (int i = ; i <= n; i++) printf(" %d", ans[i]);
printf("\n");
}
return ;
}

线段树

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
int ans[maxn];
int n;
struct node {
int h, k;
node(int h = , int k = ) :h(h), k(k) {}
}ex[maxn]; bool cmp(node a, node b) {
return a.h < b.h;
}
int sum[maxn]; int lowbit(int x)
{
return x & (-x);
} void update(int i,int k)
{
while(i<n)
{
sum[i] += k;
i += lowbit(i);
}
} int getsum(int x)
{
int res = ;
while(x>)
{
res += sum[x];
x -= lowbit(x);
}
return res;
} int main() {
int t, cnt = ;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
sum[i] = ;
int h, k;
scanf("%d%d", &h, &k);
ex[i] = node(h, k);
}
int flag = ;
sort(ex + , ex + + n, cmp);
for (int i = ; i <= n; i++) {
if (n - i - ex[i].k < ) {
flag = ;
break;
}
ex[i].k = min(ex[i].k, n - i - ex[i].k);
}
if (flag) {
printf("Case #%d: impossible\n", ++cnt);
continue;
}
for (int i = ; i <= n; i++) {
int l = ex[i].k + , r = n;
int num = ex[i].k + ;
while (l <= r) {
int mid = (l + r) >> ;
int res = mid - getsum(mid), e = getsum(mid) - getsum(mid - );
// if (res == num && e == 0) {
// ans[mid] = ex[i].h;
// update(mid, 1);
// flag1 = 1;
// break;
// }
if (res >= num) r = mid - ;
else l = mid + ;
}
ans[r + ] = ex[i].h;
update(r + , );
}
printf("Case #%d:", ++cnt);
for (int i = ; i <= n; i++) printf(" %d", ans[i]);
printf("\n");
}
return ;
}

树状数组

G - Queue HDU - 5493 线段树+二分的更多相关文章

  1. L - Vases and Flowers HDU - 4614 线段树+二分

    题意 给出一排空花瓶 有两种操作  1是 从A花瓶开始放F朵花 如果当前瓶有花就跳过前往下一个 直到花用完或者 瓶子到了最后一个为止 输出 成功放花的第一个和最后一个  如果没有输出 can not. ...

  2. Q - Queue HDU - 5493(树状树组维护区间前缀和 + 二分找预留空位)

    Q - Queue HDU - 5493 Problem Description NNN people numbered from 1 to NNN are waiting in a bank for ...

  3. hdu4614 线段树+二分 插花

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  4. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  5. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  6. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. hdu 1828 线段树扫描线(周长)

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  9. hdu 4747 线段树

    Mex Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

随机推荐

  1. Nexus3 集成 crowd 插件

    公司使用的软件开发和协作工具为 Atlassian 系列软件,所以统一使用 crowd 来实现统一登录(SSO). crowd 配置 具体操作细节见我之前写的 Atlassian 系列软件安装(Cro ...

  2. 用three.js开发三维地图实例

    公司要做智慧消防楼层可视化,需要用到web3d,开源的引擎中先研究了cesium三维地球,但cesium做楼层感觉是大材小用,而且体验也不好,最终选用的是功能强大.更适合小型场景的three. thr ...

  3. L16 LeNet

    **本小节用到的数据下载 1.涉及语句 import d2lzh1981 as d2l 数据1 : d2lzh1981 链接:https://pan.baidu.com/s/1LyaZ84Q4M75G ...

  4. vue2.x学习笔记(九)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12577948.html. 数组的更新检测 数组在javascript是一种特殊的对象,不是像普通的对象那样通过Ob ...

  5. 详解 Map集合

    (请关注 本人"集合总集篇"博文--<详解 集合框架>) 首先,本人来讲解下 Map集合 的特点: Map集合 的特点: 特点: 通过 键 映射到 值的对象 一个 映射 ...

  6. 解析网站爬取腾讯vip视频

    今天用油猴脚本vip一件解析看神奇队长.想到了问题,这个页面应该是找到了视频的api的接口,通过接口调用获取到了视频的地址. 那自己找腾讯视频地址多费劲啊,现在越来越多的参数,眼花缭乱的. 那我就找到 ...

  7. Jmeter 使用正则表达式提取响应结果中的值

    正则表达式提取的界面如下图: apply to: Main sample and sub-samples:作用于父节点取样器及对应子节点取样器Main sample only:仅作用于父节点取样器Su ...

  8. [linux] 小问题:管道符,换行问题等;[nginx]启动,重启,关闭命令;以及升级nginx切换命令

    Lniux换行问题 后面回车不会马上执行本条命令而是换行继续. : 是运行完前面就继续后面的, && 同样是前面正确就运行后面, || 是前面运行不正确就运行后面. | 管道符“|”将 ...

  9. HBase Filter 过滤器之 Comparator 原理及源码学习

    前言:上篇文章HBase Filter 过滤器概述对HBase过滤器的组成及其家谱进行简单介绍,本篇文章主要对HBase过滤器之比较器作一个补充介绍,也算是HBase Filter学习的必备低阶魂技吧 ...

  10. Ansible playbook 编程

    Ansible playbook 编程详解与各种小案例 主机规划 添加用户账号 说明: 1. 运维人员使用的登录账号: 2. 所有的业务都放在 /app/ 下「yun用户的家目录」,避免业务数据乱放: ...