G - Queue HDU - 5493 线段树+二分
G - Queue
题目大意:给你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 线段树+二分的更多相关文章
- L - Vases and Flowers HDU - 4614 线段树+二分
题意 给出一排空花瓶 有两种操作 1是 从A花瓶开始放F朵花 如果当前瓶有花就跳过前往下一个 直到花用完或者 瓶子到了最后一个为止 输出 成功放花的第一个和最后一个 如果没有输出 can not. ...
- Q - Queue HDU - 5493(树状树组维护区间前缀和 + 二分找预留空位)
Q - Queue HDU - 5493 Problem Description NNN people numbered from 1 to NNN are waiting in a bank for ...
- hdu4614 线段树+二分 插花
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...
- 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 ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 2871 线段树(各种操作)
Memory Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu 4747 线段树
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
随机推荐
- 一个java 码手 的老牛 --- 涉及 一些不错的java 基础课程
http://www.zuidaima. com/user/1550463811307520/share/collect.htm
- 前端学习笔记 --ES6新特性
前言 这篇博客是我在b站进行学习es6课程时的笔记总结与补充. 此处贴出up主的教程视频地址:深入解读ES6系列(全18讲) 1.ES6学习之路 1.1 ES6新特性 1. 变量 2. 函数 3. 数 ...
- JuiceSSH:安卓平台免费好用的 SSH 客户端
为了解决上下班路上或者没带电脑时,查看 Linux 服务器日志或者紧急运维的需求,最终找到了 JuiceSSH 这款软件,强烈推荐给大家. 简介 JuiceSSH 是一个为 Android 打造的全功 ...
- 教你如何安装和使用Python pip
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Starshot PS:如有需要Python学习资料的小伙伴可以加点击 ...
- stand up meeting 11/16/2015
第一周,熟悉任务中~ 大致写下一天的工作: 冯晓云:熟悉bing接口,本意是调在线的必应词典API,参阅了大量C#调用API开发.net的工作,[约莫是因为有个窗口互动性更强,所以这样的工作更有趣,也 ...
- 基于Python的Webservice开发(四)-泛微OA的SOAP接口
一.功能需求 泛微e-cology可以在流程中调用Webservice接口实现与其他系统的联动等复杂功能.但是目前泛微文档中仅提供了调用的方法,但是没有关于接口的相关开发信息. 本次案例是用Pytho ...
- Java8新特性(1):Lambda表达式
Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表.函数主体.返回类型.它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数. ...
- Spring5:面向切面
静态代理 缺点:一个真实角色就会产生一个代理角色,代码量会翻倍! 场景:要在写好的实现方法上加入日志功能(公共功能),不要修改原代码 1:原代码 业务接口: package com.spring; p ...
- JDBC教程——检视阅读
JDBC教程--检视阅读 参考 JDBC教程--W3Cschool JDBC教程--一点教程,有高级部分 JDBC教程--易百 JDBC入门教程 – 终极指南 略读 三层架构详解,JDBC在数据访问层 ...
- 支付宝开源非侵入式 Android 自动化测试工具 Soloπ
Soloπ(SoloPi)是支付宝开源的一个无线化.非侵入式的Android自动化测试工具,公测版拥有录制回放.性能测试.一机多控三项主要功能,能为测试开发人员节省宝贵时间. 本文是SoloPi团队关 ...