【CSP模拟赛】奇怪的队列(树状数组 &二分&贪心)
题目描述
nodgd的粉丝太多了,每天都会有很多人排队要签名。
今天有n个人排队,每个人的身高都是一个整数,且互不相同。很不巧,nodgd今天去忙别的事情去了,就只好让这些粉丝们明天再来。同时nodgd提出了一个要求,每个人都要记住自己前面与多少个比自己高的人,以便于明天恢复到今天的顺序。
但是,粉丝们或多或少都是有些失望的,失望使她们晕头转向、神魂颠倒,已经分不清楚哪一边是“前面”了,于是她们可能是记住了前面比自己高的人的个数,也可能是记住了后面比自己高的人的个数,而且他们不知道自己记住的是哪一个方向。
nodgd觉得,即使这样明天也能恢复出一个排队顺序,使得任意一个人的两个方向中至少有一个方向上的比他高的人数和他记住的数字相同。可惜n比较大,显然需要写个程序来解决,nodgd很忙,写程序这种事情就交给你了。
输入格式
第一行输入一个整数n,表示指令的条数。(n<=100000,身高在整型范围)
接下来n行,每行两个整数ai,bi,表示一个人的身高和她记住的数字,保证身高互不相同。
输出格式
输出一行,这个队列里从前到后的每个人的身高。如果有多个答案满足题意,输出字典序最小。如果不存在满足题意的排列,输出“impossible”
输入样例
4
4 1
3 1
6 0
2 0
输出样例
2 4 3 6
提示
在所给出的答案队列中,第一个人身高为2,前面有0个人比他高,所以他是输入的第4个人;第二个人身高为4,右边有1个人比他高,所以他是输入的第1个人;第三个人身高为3,右边有1个人比他高,所以他是输入的第2个人;第四个人身高为6,左边有0个人比他高,所以他是输入的第3个人。
显然,如果排列为“6 3 4 2”也是满足题意的,但是字典序不是最小的
分析
这个题的思路难以表述,可我还是要来强行口胡一波
考虑从小到大进行插入,因为这样可以在插入时贪心尽量控制字典序最小,即把当前的人尽量往前放。
我们先预处理出对于每个人,有多少个人比她高,如果比她高的人的个数小于她所记住的数则无解。
然后能够算出她前面最少有多少个人比她高,假设为k个
那么她插入时,因为是从小到大插入的,所以前面就应该预留k个空位给比她高的人,她就在第k+1个空位处
这样就既可以保证有解,还可以保证字典序最小。
但如果存在相同高度的人时,可能前面应该预留不止k个空格,因为后面的插入可能会占用某个空格却不作贡献
即如果两个人高度相同,k较大的人先插入,k较小的后插入,k较小的人就会破坏k较大的人所预留出来的空位
如图,1号的高度与2号相等,1号的k=5,2号的k=2

1号插入时给比她高的人留了k个空位

但是当2号插入时会占用一个空位却不作出贡献
而先插入2号再插入1号就不存在这样的问题


所以,遇到相同高度时就按k从小到大排序后在插入即可。
那么问题来了,我们如何来实现呢?
我们可以用树状数组来维护
每一个空格的值为1,这样某个位置的前缀和就是这个位置及之前共有多少个空位
显然越往右前缀和是单增的,所以可以二分确定第k个空位的位置
在插入一个人的时候,先二分出第k+1空位的位置,记录答案,然后在树状数组中修改这个位置的值,再去插入下一个人
复杂度为O(nlog^2n)。好像树状数组还有nlogn的做法,但我想咕了。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n,vis[],bit[],ans[];
struct node{int h,id;}st[];
void add(int x,int k){for(;x<=n;x+=(x&-x))bit[x]+=k;}
bool cmp(node a,node b){return a.h==b.h?a.id<b.id:a.h<b.h;}
int que(int x){int s=;for(;x;x-=(x&-x))s+=bit[x];return s;}
int main()
{
scanf("%d",&n);for(int i=;i<=n;i++)scanf("%d%d",&st[i].h,&st[i].id);
sort(st+,st++n,cmp);int flag=;
for(int i=,l,r;i<=n;add(i,),i++)
{
l=r=i;while(st[i].h==st[i+].h)i++,r++;
for(int j=l;j<=r;j++)flag|=(st[j].id=min(n-r-st[j].id,st[j].id))<;
}
if(flag)return puts("impossible"),;sort(st+,st++n,cmp);
for(int i=;i<=n;i++)
{
int l=,r=n,mid,pos;
while(l<=r)
{
mid=(l+r)>>;
if(que(mid)>=st[i].id+)r=mid-,pos=mid;
else l=mid+;
}
add(pos,-);
ans[pos]=st[i].h;
}
for(int i=;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
}
【CSP模拟赛】奇怪的队列(树状数组 &二分&贪心)的更多相关文章
- 模拟赛 T3 DFS序+树状数组+树链的并+点权/边权技巧
题意:给定一颗树,有 $m$ 次操作. 操作 0 :向集合 $S$ 中加入一条路径 $(p,q)$,权值为 $v$ 操作 1 :给定一个点集 $T$,求 $T$ 的并集与 $S$ 中路径含交集的权和. ...
- 【题解】Leyni,罗莉和队列(树状数组)
[题解]Leyni,罗莉和队列(树状数组) HRBUST - 1356 将整个序列reverse一下,现在就变成了从高到低的排队.题目就变成了,定位一个妹子,问这个妹子前面的比这个妹子小的妹子中,下标 ...
- POJ 2182 Lost Cows 【树状数组+二分】
题目链接:http://poj.org/problem?id=2182 Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- 牛客多校第3场 J 思维+树状数组+二分
牛客多校第3场 J 思维+树状数组+二分 传送门:https://ac.nowcoder.com/acm/contest/883/J 题意: 给你q个询问,和一个队列容量f 询问有两种操作: 0.访问 ...
- POJ 2828 Buy Tickets (线段树 or 树状数组+二分)
题目链接:http://poj.org/problem?id=2828 题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的. 反过来做就很容易了,从最后一个人开始推,最后一个人位置很容 ...
- TZOJ 4602 高桥和低桥(二分或树状数组+二分)
描述 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算“淹了两次”.举 ...
- 树状数组+二分||线段树 HDOJ 5493 Queue
题目传送门 题意:已知每个人的独一无二的身高以及排在他前面或者后面比他高的人数,问身高字典序最小的排法 分析:首先对身高从矮到高排序,那么可以知道每个人有多少人的身高比他高,那么取较小值(k[i], ...
- P2161 [SHOI2009]会场预约[线段树/树状数组+二分/STL]
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- The Stream of Corning 2( 权值线段树/(树状数组+二分) )
题意: 有两种操作:1.在[l,r]上插入一条值为val的线段 2.问p位置上值第k小的线段的值(是否存在) 特别的,询问的时候l和p合起来是一个递增序列 1<=l,r<=1e9:1< ...
随机推荐
- rabbitmq使用教程
检查RabbitMQ运行状态1)打开命令行命令行,进入RabbitMQ的安装目录: cd D:\installs\rabbitmq\rabbitmq_server-3.7.15\sbin2)输入 ra ...
- pythdon day13:网络编程socket
目录 day 13 learning python 49. 网络基础 49.1 IP地址 49.2 协议 50. socket编程(套接字编程) 50.1 socket编程简介 50.2 创建sock ...
- Jenkins多环境持续集成架构实践
自动化部署主要是为了解决项目多.环境多.持续集成慢.部署操作麻烦.手动操作易出错.自动化运维等问题. Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建.部署.自动化 ...
- 大学课后答案微信小程序项目实践(1)
叨逼叨 还记得以前小编上大学那会苦于课后习题没有答案...到了考试....就像下面这个图一样- 现在,那些同样在纠结于书本后的答案太遥远的同学们,要告诉你们一个好消息,个人历时两周作业的时间开发的小程 ...
- 浦发银行网上银行U盾证书无法更新的解决办法
浦发银行需要更新证书.很多浦发客户都会碰到题主一样更新证书失败的困扰.网银登录似乎一切正常,可是等待进入个人网银时却跳出提示,如下图: 没有选择,只能点击确定,然后就是: 再“确定”下去: 再确定就出 ...
- DTD学习
DTD 简介 文档类型定义(DTD)可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档的结构.DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用. XML文件内部引用: 外部 ...
- redis 设置密码并运行外部连接
redis默认是不能远程访问的,如果希望多台机子共用redis数据库,那就需要开启redis远程连接访问.既然可以远程连接了,那就需要密码登陆,否则不安全.下面是具体的方法,按照步骤一步一步来就OK了 ...
- Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapt ...
- Dubbo源码分析(3):ExtensionFactory
通过ExtensionFactory的getExtension方法获取目标对象.ExtensionFactory实现有两个,一个基于SPI的,一个Spring的ApplicationContext的. ...
- Mybatis下Oracle插入新增返回主键id
具体xml中sql是这样写,但是要注意SQ_USER.Nextval,SQ_USER是序列,你要替换下自己要进行操作的表的序列,不知道序列的话,可以sql查找下,select * from user_ ...