当前位置: 代码迷 >> 综合 >> 【Codeforces Round #111 (Div. 2) E. Buses and People】离散化+线段树
  详细解决方案

【Codeforces Round #111 (Div. 2) E. Buses and People】离散化+线段树

热度:79   发布时间:2023-12-29 02:02:58.0

链接:

Codeforces Round #111 (Div. 2) E. Buses and People

题意

有n个公交车,每个公交车的信息有sis_isi?(公交车起始下标),fif_ifi?(公交车终点下标),tit_iti?(公交车发车时间)。
有m个乘客,每个乘客的信息有lil_ili?(乘客起始下标),rir_iri?(乘客下车的下标),bib_ibi?(乘客上车时间)。
乘客iii坐上公交车jjj的前提是sj≤lis_j \leq l_isj?li?,ri≤fjr_i \leq f_jri?fj?,bi≤tjb_i \leq t_jbi?tj?,问每一个乘客能坐的公交车中发车时间最小的公交车编号。

做法

首先先将所有公交车和乘客放到一起,之后按照起始下标排序,这样就能保证每个人乘客之前的公交车一定满足sj≤lis_j \leq l_isj?li?

之后我们对时间进行离散化建立线段树,每个节点存储当前t能到达的最大的fff,对于每个乘客,我们只需要查找小于等于tit_iti?的时间区间中最小的满足ri≤fjr_i \leq f_jri?fj?的t即可。

所以问题就转换为给定一个区间,求区间内最小的下标满足权值大于某个给定值。这个问题只需要在线段树上优先查询左子区间是否有满足情况的点,向下递归询问即可,注意要用区间max进行剪枝。

代码


#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 2e5+5;
struct T
{
    int l,r,mid;int val,id;
}tree[maxn<<2];
void push_up(int rt)
{
    tree[rt].val=max(tree[rt<<1].val,tree[rt<<1|1].val);
}
void build(int rt ,int l,int r)
{
    tree[rt].l=l;tree[rt].r=r;if(l==r){
    tree[rt].id=-1;tree[rt].val=0;return ;}int mid=tree[rt].mid=l+r>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);push_up(rt);
}
void update(int rt,int pos,int val,int id)
{
    if(tree[rt].l==tree[rt].r){
    tree[rt].val=max(tree[rt].val,val);tree[rt].id=id;return ;}if(pos<=tree[rt].mid) update(rt<<1,pos,val,id);else update(rt<<1|1,pos,val,id);push_up(rt);
}
int query(int rt,int val,int l,int r)
{
    if(tree[rt].l>=l&&tree[rt].r<=r){
    if(tree[rt].val<val) return -1;}if(tree[rt].l==tree[rt].r) return tree[rt].id;int ans=-1;if(tree[rt].mid>=l){
    ans=query(rt<<1,val,l,r);if(ans!=-1) return ans;}if(tree[rt].id<r){
    ans=query(rt<<1|1,val,l,r);if(ans!=-1) return ans;}return -1;
}
struct Bus
{
    int l,r,t,id;bool operator<(const Bus y)const{
    if(l==y.l) return id<y.id;//要注意一个l同时有公交车和乘客,先更新公交车信息。return l<y.l;}
}bus[maxn<<2];
int Hash[maxn<<2],cnt;
int ans[maxn<<2];
int main()
{
    int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n+m;i++){
    scanf("%d%d%d",&bus[i].l,&bus[i].r,&bus[i].t);bus[i].id=i;Hash[++cnt]=bus[i].t;}sort(bus+1,bus+1+n+m);sort(Hash+1,Hash+1+cnt);build(1,1,cnt);int d=unique(Hash+1,Hash+1+cnt)-Hash-1;//对时间进行离散化for(int i=1;i<=n+m;i++){
    int pos=lower_bound(Hash+1,Hash+1+d,bus[i].t)-Hash;if(bus[i].id<=n) update(1,pos,bus[i].r,bus[i].id);//公交车信息进行更新else ans[bus[i].id-n]=query(1,bus[i].r,pos,cnt);//乘客进行查询}for(int i=1;i<=m;i++) printf("%d ",ans[i]);return 0;
}
  相关解决方案