[牛客网] 推箱子【离散,线段树区间覆盖】

Online Judge牛客网NOIP2018赛前集训营-提高组(第八场)T2

Label:离散,线段树区间覆盖

ps:这套题目由于被改成模拟离线赛,所以下面的题目描述改编了,题目还是一样的。


题目描述

终于,今天Sheldon要坐飞机前往瑞典领诺贝尔奖了。作为Sheldon的好朋友,Leonard、Penny、Howard、Bernadette、Rajesh也会去。不过由于行李太多太重,众人只好将行李堆在电梯里后,再走楼梯到一楼静静地等电梯。

不幸的是,行李堆得太高了,电梯门一开行李就散落一地。很巧的是,如果把地板作为平面,行李近似的看成矩形,定义每块瓷砖的垂直边分别作为坐标轴,x轴的正方向向右,那么每个行李箱的每条边都平行与坐标轴,且没有重叠。

Sheldon见到此番情景,向便Leonard提出了一个问题,如果由Sheldon挑选一个行李箱,由Leonard推着这个箱子向右以每秒1个单位的速度移动。如果路上正面碰上某个行李箱,被碰上的行李箱会在碰到的那个瞬间开始进入运动状态,以1个单位的速度向右移动,不会转动或改变运动方向。考虑到Leonard是个重度哮喘症患者,所以他只能坚持k秒就要停下来。而Sheldon想知道Leonard停下来时所有行李箱的位置。

准确地说,在某个时刻一个箱子i处于移动状态当且仅当:i是选择的箱子;或者存在一个处于移动状态的箱子j,它的右边界等于箱子i的左边界,且它们在y轴上的投影的公共长度>0。你可以发现在这种情况下,任意时刻每个矩形仍然不相交。

Leonard认为这个问题太过于stupid,但又不好意思拒绝(毕竟是十年的室友),于是让老X来回答这个问题。如果老X成功地回答了Sheldon的问题,Leonard就会让Sheldon就会带上老X一起去瑞典。

输入

第一行两个整数n,t和k。Sheldon开始选择的是输入的第t个行李。接下来n行每行四个整数表示行李的左下角坐标是((x1_i,y1_i)),右上角坐标是((x2_i,y2_i))

输出

输出一行n个整数,第i个整数表示k秒后第i个行李箱的左下角的x坐标。

你可以发现只要知道这个值就能唯一确定行李箱的位置。

样例

Input

5 1 1
1 1 2 3
2 2 3 5
3 4 4 5
4 2 5 5
5 1 6 3

Output

2 3 4 5 6

Hint

对于30%的数据,(k≤100)

对于另外40%的数据,(n≤1000)

对于100%的数据,(n≤10^5,1≤t≤n,1≤k≤10^9),所有坐标都在(−10^9)(10^9)之间。

数据保证任意两个行李不相交。

题解

首先当然是根据(x1)将所有箱子排序。我们只要知道每个箱子第一次被推动的时间(ti)即可算出最后每个箱子的位置。

为避免擦着过的情况,我们一开始先将(y2--)。这样只要满足两个点纵坐标构成的两区间存在交集则表示会相撞。假设(i)会被它前面的撞到,且(i)能够撞到(j),则(ti[j]=min(ti[j],ti[i]+x1[j]-x2[i]))

对于70%数据,直接暴力(O(N))扫一遍前面的行李即可,取最小值,总的时间复杂度为(O(N^2))

考虑怎么快速取到最小值,很显然可以用线段树去优化。先将纵坐标离散了,然后对线段树的一段区间赋上某个值,这个区间就是离散后的纵坐标。查询时也是根据当前点的纵坐标区间查询最小值。存什么值呢,观察上面那个式子得,只要存(ti[i]-x2[i])即可。线段树支持个区间覆盖,区间查询最小值即可。

这道题就结束了,不过实现上有很多细节要注意:

1.最后一定要判(ti[]<=k),保证是在规定时间内被撞到。

2.由于是线段树区间赋值,一开始的懒标记lazy,最小值w一定都要赋值成一个极大值INF。

3.离散数组要开(2N),因为对于每个箱子都离散了(y1,y2)(2N)个数。相应的,线段树数组大小要开(8N)

4.一开始的(y2--),保证不会出现擦过的情况。

5.一个考试时很silly的疑惑:怎么保证按x1排序后,只要纵坐标有交集两个箱子会相撞,如果前面箱子的x2>后面箱子的x1那不就不相撞了吗,其实画个图就知道这两者不可能同时满足qwq。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,INF=1e9+2;
inline int read(){
    int x=0,e=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')e=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*e;
}
struct node{
	int x,y,x2,y2,id;
}o[N];
inline bool cmp(node a,node b){return a.x<b.x;}
int n,s,k,LIM;

struct sgt{
	int l,r,w,lazy;
}b[8*N];
void build(int o,int l,int r){
	b[o].l=l,b[o].r=r,b[o].w=INF,b[o].lazy=INF;
	if(l==r)return;
	int mid=l+r>>1;
	build(o<<1,l,mid);build(o<<1|1,mid+1,r);
}
void down(int o){
	if(b[o].lazy==INF)return ;
	int p=b[o].lazy;
	b[o<<1].w=min(b[o<<1].w,p);b[o<<1|1].w=min(b[o<<1|1].w,p);
	b[o<<1].lazy=min(b[o<<1].lazy,p);b[o<<1|1].lazy=min(b[o<<1|1].lazy,p);
	b[o].lazy=INF;
}
void update(int o,int l,int r,int d){
	if(b[o].l==l&&b[o].r==r){
		b[o].w=min(b[o].w,d);
		b[o].lazy=min(b[o].lazy,d);
		return;
	}
	down(o);
	int mid=b[o].l+b[o].r>>1;
	if(r<=mid)update(o<<1,l,r,d);
	else if(l>mid)update(o<<1|1,l,r,d);
	else{
		update(o<<1,l,mid,d);update(o<<1|1,mid+1,r,d);
	}
	b[o].w=min(b[o<<1].w,b[o<<1|1].w);
}
int query(int o,int l,int r){
	if(b[o].l==l&&b[o].r==r)return b[o].w;
	down(o);
	int mid=b[o].l+b[o].r>>1;
	if(r<=mid)return query(o<<1,l,r);
	else if(l>mid)return query(o<<1|1,l,r);
	return min(query(o<<1,l,mid),query(o<<1|1,mid+1,r));
}
int ti[N],res[N];
int yy[2*N];
int main(){
	n=read(),s=read(),k=read();
	int tmp=0;
	for(register int i=1;i<=n;i++){
		int a=read(),b=read(),c=read(),d=read();
		d--;	
		o[i]=(node){a,b,c,d,i};
		yy[++tmp]=b,yy[++tmp]=d;
	}
	sort(o+1,o+n+1,cmp);
	sort(yy+1,yy+tmp+1);
	LIM=unique(yy+1,yy+tmp+1)-yy-1;
	
	for(register int i=1;i<=n;i++){
		o[i].y=lower_bound(yy+1,yy+LIM+1,o[i].y)-yy;
		o[i].y2=lower_bound(yy+1,yy+LIM+1,o[i].y2)-yy;
	}
	build(1,1,LIM);
	int st;
	for(register int i=1;i<=n;i++)if(o[i].id==s){st=i;break;}
	ti[st]=1;
	update(1,o[st].y,o[st].y2,1-o[st].x2);
	for(register int i=st+1;i<=n;i++){
		int now=query(1,o[i].y,o[i].y2);	
		if(now==INF)continue;
		ti[i]=o[i].x+now;
		update(1,o[i].y,o[i].y2,ti[i]-o[i].x2);
	}
	for(register int i=1;i<=n;i++){
		if(ti[i]&&ti[i]<=k)res[o[i].id]=k-ti[i]+1+o[i].x;
		else res[o[i].id]=o[i].x;
	}
	for(register int i=1;i<n;i++)printf("%d ",res[i]);
	printf("%d
",res[n]);
} 
原文地址:https://www.cnblogs.com/Tieechal/p/11488032.html