题意
有一群人要坐公交车。
人的路线和车的看路线在同一个数轴上。
人
i
i
i要从
l
i
l_i
li到
r
i
r_i
ri并在时间
b
i
b_i
bi开始在
l
i
l_i
li这个点等车。
车
i
i
i从
s
i
s_i
si开到
f
i
f_i
fi并在时间
t
i
t_i
ti从
s
i
s_i
si出发。
车开得很快,相当于瞬时到达且停靠每一个经过的点。
人只能上来得不早于他的车且不能换车。
思路
首先题目给的条件可以知道:
- 只有车行的路程完全包括人行的路程且车来得不比人早,也就是 s i ≤ l j & & f i ≥ r j & & t i ≥ b j s_i\le l_j \&\& f_i \ge r_j \&\& t_i \ge b_j si≤lj&&fi≥rj&&ti≥bj时,人 j j j才能乘坐车 i i i。
- 人肯定坐得是最早且不比他早到的那辆车。
显然可以用
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)爆扫求出答案,但也显然会T。
所以需要一种更优的解法。
由于考虑到有左端点,右端点,时间三维,你可以用高级数据结构(平衡树),或是偏序做此题(可惜我都不会)。于是只能用线段树加一些操作卡过去。
解法
先将所有的时间离散化(这样可以用作线段树的下标),然后将所有左端点排序(排掉一维)。然后按左端点从小到大枚举(相同时车在前),如果是车,将车的 i d id id和右端点插入线段树(线段树里记录某个时间段能达到的最右端点和对应的车的id),如果是人,就在线段树中查询最优的车。这样可以达到 Θ ( n l o g ( n ) ) \Theta(n log(n)) Θ(nlog(n))。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const int Mx=1e5+5;
#define FST youxiaokelianyouwuzhu
struct Buses{
LL l,r,t,id;
#define B buses
}buses[Mx];
struct Person{
LL l,r,t,id;
#define P person
}person[Mx];
LL ans[Mx],t[Mx<<1];
int n,m;
class SegTree{
public:
#define s segnode
#define I inline
#define ls k<<1
#define rs k<<1|1
I void buildSegTree(int k,int l,int r){
s[k].l=l;s[k].r=r;
if(l==r)return;
int mid=(l+r)>>1;
buildSegTree(ls,l,mid);
buildSegTree(rs,mid+1,r);
}
I void opi(int i){
int id=lower_bound(t+1,t+n+m+1,B[i].t)-t;
insert(1,id,B[i].id,B[i].r);
}
I void ops(int i){
int id=lower_bound(t+1,t+n+m+1,P[i].t)-t;
ans[P[i].id]=search(1,id,P[i].r);
}
private:
struct SegNode{
int l,r,id;
LL v;
}segnode[Mx<<3];
void pushUp(int k){
s[k].v=max(s[ls].v,s[rs].v);
}
I void insert(int k,int pos,int id,LL v){
int sl=s[k].l,sr=s[k].r;
if(sl==sr){s[k].v=v;s[k].id=id;return;}
int mid=(sl+sr)>>1;
if(pos<=mid)insert(ls,pos,id,v);
if(pos>mid)insert(rs,pos,id,v);
pushUp(k);
}
I int search(int k,int pos,LL v){
int sl=s[k].l,sr=s[k].r;
if(s[k].v<v)return -1;
if(s[k].r<pos)return -1;
if(sl==sr)return s[k].id;
int mid=(sl+sr)>>1;
int res=search(ls,pos,v);
return res==-1?search(rs,pos,v):res;
}
#undef s
#undef I
#undef ls
#undef rs
};SegTree T;
template<class T>
bool cmp(T a,T b){return a.l<b.l;};
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&B[i].l,&B[i].r,&B[i].t),B[i].id=i;
for(int i=1;i<=m;i++)scanf("%lld%lld%lld",&P[i].l,&P[i].r,&P[i].t),P[i].id=i;
T.buildSegTree(1,1,n+m);
for(int i=1;i<=n;i++)t[i]=B[i].t;
for(int i=n+1;i<=n+m;i++)t[i]=P[i-n].t;
sort(t+1,t+1+n+m);
sort(B+1,B+1+n,cmp<Buses>);
sort(P+1,P+1+m,cmp<Person>);
int bi=1,pi=1;
while(bi<=n||pi<=m){
if(pi>m)break;
if(bi>n||B[bi].l>P[pi].l)T.ops(pi),pi++;
else T.opi(bi),bi++;
}
for(int i=1;i<=m;i++)printf("%lld ",ans[i]);
}