Codeforces190 E. Buses and People(线段树上二分)

题意:

有n个公交车,每个公交车有起始位置s,终止位置f,到达终点的时间t
有m个乘客,每个乘客有上车位置l,下车位置r,上车时间b
乘客能上车的前提是l>=s,r<=f,b<=t
问每个乘客能做的公交车中,发车时间最早的车编号

数据范围n<=1e5,其他数据<=1e9,保证所有车的发车时间不同

解法:

将车和乘客按左端点从小到大排序,降一维。
双指针,遍历乘客,将左端点小于等于当前乘客的车加入线段树,
线段树每个节点表示时间,存储时间为t的车右端点

查询就是线段树中找车的时间晚于乘客的所有位置中,满足右端点大于乘客的最小时间,
可以在树上二分,优先找左子树,还可以维护一个区间max进行剪枝。

时间需要离散化

ps:
题目已经说了所有车的发车时间不同,似乎也暗示了从时间入手

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
struct E1{
    int s,f,t,id;
}e[maxm];
struct E2{
    int l,r,b,id;
}q[maxm];
bool cmp1(E1 a,E1 b){
    return a.s<b.s;
}
bool cmp2(E2 a,E2 b){
    return a.l<b.l;
}
//
int a[maxm<<2],idx[maxm<<2];
int xx[maxm],num;
int ans[maxm];
int n,m;
void pushup(int node){
    a[node]=max(a[node*2],a[node*2+1]);
}
void update(int x,int val,int idd,int l,int r,int node){
    if(l==r){
        a[node]=val;
        idx[node]=idd;
        return ;
    }
    int mid=(l+r)/2;
    if(x<=mid)update(x,val,idd,l,mid,node*2);
    else update(x,val,idd,mid+1,r,node*2+1);
    pushup(node);
}
int ask(int st,int ed,int val,int l,int r,int node){//发车时间[x,n]中满足右端点>val的最左边的车
    if(a[node]<val)return -1;
    if(l==r)return idx[node];
    int mid=(l+r)/2;
    int ans=-1;
    if(st<=mid)ans=ask(st,ed,val,l,mid,node*2);
    if(ans==-1&&ed>mid)ans=ask(st,ed,val,mid+1,r,node*2+1);
    return ans;
}
//
signed main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&e[i].s,&e[i].f,&e[i].t);
        e[i].id=i;
        xx[++num]=e[i].t;
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].b);
        q[i].id=i;
        xx[++num]=q[i].b;
    }
    sort(e+1,e+1+n,cmp1);
    sort(q+1,q+1+m,cmp2);
    //
    sort(xx+1,xx+1+num);
    num=unique(xx+1,xx+1+num)-xx-1;
    for(int i=1;i<=n;i++){
        e[i].t=lower_bound(xx+1,xx+1+num,e[i].t)-xx;
    }
    for(int i=1;i<=m;i++){
        q[i].b=lower_bound(xx+1,xx+1+num,q[i].b)-xx;
    }
    //
    int k=1;
    for(int i=1;i<=m;i++){
        while(k<=n&&e[k].s<=q[i].l){//将左端点早于当前乘客的所有车加入线段树
            update(e[k].t,e[k].f,e[k].id,1,num,1);
            k++;
        }
        ans[q[i].id]=ask(q[i].b,num,q[i].r,1,num,1);
    }
    for(int i=1;i<=m;i++){
        printf("%d ",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107453504