[CF160E](Buses and People)
题意:
有n辆公交车,每辆公交车有s(起始点),f(终点),t(发车时间) (行驶不需要时间)
有m个人,每个人有l(起点),r(终点),t(出现时间)
每个人出现后会选择最早经过他且可行的公交车
(即满足s<=l,r<=f,且公交车发车时间晚于人出现时间)
输出每个人会选择那一辆公交车
solution:
将人和车一起sort
按左端点从左到右
且人要在车后面
于是就可以不考虑左端点
限制条件还剩下时间,右端点
考虑以时间为元素建线段树并维护右端点的最大值
当然时间点要离散
code:
#include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<vector> #define ls (now<<1) #define rs (now<<1|1) #define mid ((l+r)/2) #define N 4008000 #define M 200005 #define inf 1000000007 using namespace std; vector<int>v; int find(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;} struct zero{ int rx,id;//rx:该节点l到r区间内的右端点最大值,id:该最大值所代表的车次 }tree[N]; struct sett{ int l,r,t; int id; bool operator<(const sett &p)const{ if(l==p.l)return id<p.id; return l<p.l; } }lib[M<<1]; int Ans[M]; int n,m; void push_up(int now){ tree[now].rx=max(tree[ls].rx,tree[rs].rx); } void build(int now,int l,int r){if(l==r){ tree[now].rx=-inf; return; } build(ls,l,mid); build(rs,mid+1,r); push_up(now); } void update(int now,int l,int r,int pos,int kl,int pl){//单点修改 if(l==r){ tree[now].rx=kl,tree[now].id=pl; return; } if(mid<pos)update(rs,mid+1,r,pos,kl,pl); else update(ls,l,mid,pos,kl,pl); push_up(now); } int query(int now,int l,int r,int pos,int kl){ if(tree[now].rx<kl)return -1;//now下没有可行的车次 if(l==r)return tree[now].id; int ans=-1; if(pos<=mid){ ans=query(ls,l,mid,pos,kl); if(ans>0)return ans;//能往左走就往左走(使时间最小) } return query(rs,mid+1,r,pos,kl); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n+m;i++){ scanf("%d%d%d",&lib[i].l,&lib[i].r,&lib[i].t); lib[i].id=i; v.push_back(lib[i].t); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());//离散 build(1,1,v.size()); sort(lib+1,lib+n+m+1); for(int i=1;i<=n+m;i++){
int plk=find(lib[i].t); if(lib[i].id<=n)update(1,1,v.size(),plk,lib[i].r,lib[i].id); else Ans[lib[i].id-n]=query(1,1,v.size(),plk,lib[i].r); } for(int i=1;i<=m;i++)printf("%d ",Ans[i]); }