牛客网 提高组第8周 T2 推箱子 解题报告
推箱子
链接:
https://ac.nowcoder.com/acm/contest/176/B
来源:牛客网
题目描述
在平面上有\(n\)个箱子,每个箱子都可以看成一个矩形,两条边都和坐标轴平行。任何两个矩形都不相交,但可能有某个点或某条边重合。约定\(x\)轴正方向为右,\(y\)轴正方向为上。
现在\(\tt{Fizzydavid}\)要推这些箱子。他会选择某个箱子开始,并以每秒\(1\)个单位的速度使这个箱子向右移动。如果路上正面碰上某个箱子,被碰上的箱子会在碰到的那个瞬间开始进入运动状态,以\(1\)个单位的速度向右移动,不会转动或改变运动方向。
准确地说,在某个时刻一个箱子\(i\)处于移动状态当且仅当:\(i\)是选择的箱子,或者存在一个处于移动状态的箱子\(j\),它的右边界等于箱子\(i\)的左边界,且它们在\(y\)轴上的投影的公共长度\(>0\)。你可以发现在这种情况下,任意时刻每个矩形仍然不相交。
\(\tt{Fizzydavid}\)告诉了你所有的信息,需要你求出\(k\)秒后每个矩形的位置。
输入描述:
第一行两个整数\(n\),\(t\)和\(k\)。\(\tt{Fizzydavid}\)开始选择的是输入的第\(t\)个矩形。
接下来\(n\)行每行四个整数\(x_{1,i},y_{1,i},x_{2,i},y_{2,i}\),表示矩形的左下角坐标是\((x_{1,i},y_{1,i})\),右上角坐标是\((x_{2,i},y_{2,i})\)。
输出描述:
输出一行\(n\)个整数,第\(i\)个整数表示\(k秒\)后第\(i\)个矩形的左下角的\(x\)坐标。你可以发现只要知道这个值就能唯一确定矩形的位置。
说明
对于\(30\%\)的数据,\(k\le 100\)。
对于另外\(40\%\)的数据,\(n\le 1000\)。
对于所有的数据,\(n\le 10^5\),\(1\le t\le n\),\(1\le k\le 10^9\),所有坐标都在\(-10^9\)和\(10^9\)之间。保证任意两个矩形不相交。
据说正解是优化连边最短路算法?为什么不试试类似扫描线的算法呢?(考场上线段树数组开小爆\(70\)了
按照矩形的左边界\(x\)坐标为关键字进行排序,从最开始的那个矩形一个一个做过去。
具体的,对矩形在\(y\)轴方向的凸起用线段树维护,每次加入一个矩形的时候查询\(y\)上面区间的最大值,然后看能不能顶到\(\tt{Ta}\)
支持区间赋值和区间最大值就可以了,离散化和动态开点都可以。注意覆盖情况的小细节。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=2e5+10;
struct node
{
int s,t,l,r,id;
bool friend operator <(node n1,node n2){return n1.s<n2.s;}
}mat[N];
int y[N<<1],cnt,n,t,k;
int tag[N<<2],mx[N<<2],ans[N],Time[N];
#define ls id<<1
#define rs id<<1|1
int max(int x,int y){return x>y?x:y;}
void pushdown(int id)
{
if(~tag[id])
{
mx[ls]=mx[rs]=tag[ls]=tag[rs]=tag[id];
tag[id]=-1;
}
}
void change(int id,int L,int R,int l,int r,int d)
{
if(l==L&&r==R)
{
mx[id]=max(mx[id],d);
tag[id]=mx[id];
return;
}
pushdown(id);
int Mid=L+R>>1;
if(r<=Mid) change(ls,L,Mid,l,r,d);
else if(l>Mid) change(rs,Mid+1,R,l,r,d);
else change(ls,L,Mid,l,Mid,d),change(rs,Mid+1,R,Mid+1,r,d);
mx[id]=max(mx[ls],mx[rs]);
}
int query(int id,int L,int R,int l,int r)
{
if(l==L&&r==R) return mx[id];
pushdown(id);
int Mid=L+R>>1;
if(r<=Mid) return query(ls,L,Mid,l,r);
else if(l>Mid) return query(rs,Mid+1,R,l,r);
else return max(query(ls,L,Mid,l,Mid),query(rs,Mid+1,R,Mid+1,r));
}
int main()
{
memset(tag,-1,sizeof(tag));
memset(mx,-1,sizeof(mx));
scanf("%d%d%d",&n,&t,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&mat[i].s,&mat[i].l,&mat[i].t,&mat[i].r);
--mat[i].r;
y[++cnt]=mat[i].r,y[++cnt]=mat[i].l,mat[i].id=i;
}
std::sort(y+1,y+1+cnt);
cnt=std::unique(y+1,y+1+cnt)-y-1;
for(int i=1;i<=n;i++)
{
mat[i].l=std::lower_bound(y+1,y+1+cnt,mat[i].l)-y;
mat[i].r=std::lower_bound(y+1,y+1+cnt,mat[i].r)-y;
}
std::sort(mat+1,mat+1+n);
for(int i=1;i<=n;i++) if(t==mat[i].id) {t=i;break;}
int d=mat[t].s;
change(1,1,cnt,mat[t].l,mat[t].r,mat[t].t-d);
Time[t]=k;
for(int i=t+1;i<=n;i++)
{
int dis=query(1,1,cnt,mat[i].l,mat[i].r);
if(dis==-1) continue;
if(k>=mat[i].s-(dis+d))
{
k-=mat[i].s-(dis+d);
d+=mat[i].s-(dis+d);
change(1,1,cnt,mat[i].l,mat[i].r,mat[i].t-d);
Time[i]=k;
}
else
break;
}
for(int i=1;i<=n;i++)
ans[mat[i].id]=mat[i].s+Time[i];
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
return 0;
}
2018.11.4
牛客网 提高组第8周 T2 推箱子 解题报告的更多相关文章
- 牛客网 提高组第8周 T1 染色
染色 链接: https://ac.nowcoder.com/acm/contest/176/A 来源:牛客网 题目描述 \(\tt{fizzydavid}\)和\(\tt{leo}\)有\(n\)个 ...
- 18/9/16牛客网提高组Day2
牛客网提高组Day2 T1 方差 第一眼看就知道要打暴力啊,然而并没有想到去化简式子... 可能因为昨晚没睡好,今天上午困死 导致暴力打了一个半小时,还不对... #include <algor ...
- 18/9/9牛客网提高组Day1
牛客网提高组Day1 T1 中位数 这好像是主席树??听说过,不会啊... 最后只打了个暴力,可能是n2logn? 只过了前30% qwq #include<algorithm> #in ...
- nowcoder(牛客网)提高组模拟赛第四场 解题报告
T1 动态点分治 就是模拟..... 但是没有过!! 看了题解之后发现.... 坑点:有可能 \(x<=r\),但是
- 牛客网提高组模拟赛第七场 T3 洞穴(附bitset介绍)
就是DP. 我们可以很简单的想到要枚举中间点,进行边数的转移. 但是因为边长数据范围很大,所以我们考虑log的倍增. 状态设计为\(dp[i][j][k]\),为从节点\(i\)走\(2^k\)步能否 ...
- 牛客网提高组模拟赛第七场 T2 随机生成树
其实看懂题就很水啦qwq,就是求\(1-N\)的约数啦. 暴力求的话时间复杂度是\(O(NlogN)\)的,其实正解是枚举每个数的倍数......这样的时间复杂度是\(\frac{N}{1}+\fra ...
- 牛客网提高组模拟赛第五场 T1同余方程(异或)(位运算)
区间不好做,但是我们可以转化成前缀来做.转化为前缀之后之后就是二维前缀和. 但是我还是不怎么会做.所以只能去看吉老师的题解 (确定写的那么简单真的是题解???). 我们要求模一个数余0,就等于找它的倍 ...
- nowcoder(牛客网)提高组模拟赛第一场 解题报告
T1 中位数(二分) 这个题是一个二分(听说是上周atcoder beginner contest的D题???) 我们可以开一个数组b存a,sort然后二分b进行check(从后往前直接遍历check ...
- 牛客网提高组第二场---solution
T1 方差 根据题目要求将式子先写出来注意下面式子中的 $n$ 全部都是 $n-1$$$\begin{aligned}ans&=n^2\times \frac{1}{n}\times \sum ...
随机推荐
- WEB框架概述(译)
在学习WEB框架之前,我个人觉得需要搞清楚一件事:什么是WEB框架?在网上找了很多资料,觉得什么是WEB框架这篇文章讲的比较全面而清晰,本文作者Jeff Knupp. 全文如下: Web 应用框架,或 ...
- 关于BLOB/TEXT字段存储设计及性能的简单研究
简单研究了一下BLOB/TEXT字段对数据库性能的影响,得到一个大概的结论:(未验证) 无论MySQL还是MSSQL,都可以通过把BLOB/TEXT数据存储在行外的方式提高性能 把BLOB/TEXT字 ...
- Unity AssetBundle工作流
一.创建AssetBundle 1.在资源的Inspector视图下有一个AssetBundle的UI,第一个选项表示AssetBundle名称,第二个用于设置AssetBundle Variant, ...
- 【廖雪峰老师python教程】——IO编程
同步IO 异步IO 最常见的IO——读写文件 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一 ...
- oracle的数据对象
oracle的数据对象包括表.视图.约束.序列.索引.函数.存储过程.包和触发器等. 这里主要介绍视图.序列.索引.触发器.存储过程 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以 ...
- 微信小程序入门学习之事件 事件对象 冒泡非冒泡事件(1)
这关于事件的学习,可以自己复制到微信开发者工具上自己运行试试. 首先这里有两个文件.js 和.wxml 文件 首先给出.js文件下代码 // pages/news/news.js Page({ /** ...
- 《Git学习指南》学习笔记(三)
多次提交 提交一般分未两步:add和commit. add将修改存入到索引(index)或叫暂存区(staging area)中. status命令 status命令会出现三种可能的状态: chang ...
- [Clr via C#读书笔记]Cp19可空值类型
Cp19可空值类型 主要解决的是和数据库中null对应的问题: System.Nullable结构:值类型: int?语法: 可空实例能够使用操作符: C#空合并操作符??; 即可用于引用类型,也可以 ...
- tomcat下载、安装
下载 官网地址:https://tomcat.apache.org/download-80.cgi 安装 直接安装即可.安装完毕后Tomcat的目录结构如下: bin:脚本目录 启动脚本:star ...
- vue开发学习中遇到的问题以及解决方法
1:node-sass 安装失败,可使用 cnpm 安装 npm install cnpm -g --registry=https://registry.npm.taobao.org cnpm -v ...