CodeForces - 160E Buses and People(线段树+离散化)

题目链接:http://codeforces.com/problemset/problem/160/E

题目大意:
有n辆巴士,m个人,巴士有自己的出发站,结束站和出发时间 ,每个乘客也有自己的出发站,结束站,出发时间 ,输出每个乘客会做哪一辆车完成它的目标。

E. Buses and People

time limit per test:1 second
memory limit per test:256 megabytes

The main Bertown street is represented by a straight line. There are 109 bus stops located on the line. The stops are numbered with integers from 1 to 109 in the order in which they follow on the road. The city has n buses. Every day the i-th bus drives from stop number si to stop number fi (si < fi), it stops on all intermediate stops and returns only at night. The bus starts driving at time ti and drives so fast that it finishes driving also at time ti. The time ti is different for all buses. The buses have infinite capacity.

Bertown has m citizens. Today the i-th person should get from stop number li to stop number ri (li < ri); the i-th citizen comes to his initial stop (li) at time bi. Each person, on the one hand, wants to get to the destination point as quickly as possible, and on the other hand, definitely does not want to change the buses as he rides. More formally: the i-th person chooses bus j, with minimum time tj, such that sj ≤ li, ri ≤ fj and bi ≤ tj.

Your task is to determine for each citizen whether he can ride to the destination point today and if he can, find the number of the bus on which the citizen will ride.

Input
The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of buses and the number of people.

Then n lines follow, each of them contains three integers: si, fi, ti (1 ≤ si, fi, ti ≤ 109, si < fi) — the description of the buses. It is guaranteed that all ti-s are different.

Then m lines follow, each of them contains three integers: li, ri, bi (1 ≤ li, ri, bi ≤ 109, li < ri) — the Bertown citizens’ description. Some bi-s could coincide.

Output
In the first line print m space-separated integers: the i-th number should be equal either to -1, if the person number i can’t get to the destination point, or to the number of the bus that will ride the person number i. The buses are numbered with integers from 1 to n in the input order.

Examples
input
4 3
1 10 10
5 6 2
6 7 3
5 7 4
5 7 1
1 2 1
1 10 11
output
4 1 -1

input
1 1
1 1000000000 1000000000
1 1000000000 1000000000
output
1

思路: 线段树+离散化

具体做法:
1. 把车和人放在一起按左端点排序(左端点相同,先车再人(即按id排序))

2. 分类讨论:
<1> 当前为车,将这辆车的信息按照出发时间更新入线段树中,因为是按照左端点排序,所以线段树只需保存右端点。

<2> 当前为人,此时只有线段树中已经存的结点才有可能符合要求,所以直接对线段树内的结点查询,找出最左端的一个符合要求的结点。

#include<bits/stdc++.h>
using namespace std;
const int N=100050,inf=1e9+7;
struct tree
{
    int l,r,mid,rx,id;
}t[N<<3];
struct node
{
    int l,r,t,id;
    bool operator < (const node &p) const//先按左端点排序,再按先车后人的顺序排(即按id排序)
    {
        if (l==p.l) return id<p.id;
        return l<p.l;
    }
}g[N<<1];
int n,m,ans[N];
vector <int> v;
int get(int x)//找到当前节点的位置
{
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void pushup(int rt)
{
    t[rt].rx=max(t[rt<<1].rx,t[rt<<1|1].rx);
}
void build(int l,int r,int rt)//建树
{
    int m=(l+r)>>1;
    t[rt].l=l;
    t[rt].r=r;
    t[rt].mid=m;
    if (l==r)
    {
        t[rt].rx=-inf;
        return;
    }
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(int pos,int id,int x,int rt)//更新树上的值
{
    if (t[rt].l==t[rt].r)
    {
        t[rt].rx=x;
        t[rt].id=id;
        return;
    }
    if (pos<=t[rt].mid)
    {
        update(pos,id,x,rt<<1);
    }
    if (pos>t[rt].mid)
    {
        update(pos,id,x,rt<<1|1);
    }
    pushup(rt);
}
int query(int pos,int x,int rt)//查找满足要求的最左端的点
{
    if (t[rt].rx<x) return -1;
    if (t[rt].l==t[rt].r) return t[rt].id;
    int ans=-1;
    if (pos<=t[rt].mid)
    {
        ans=query(pos,x,rt<<1);
        if (ans>0) return ans;
    }
    return query(pos,x,rt<<1|1);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n+m;i++)
    {
       scanf("%d%d%d",&g[i].l,&g[i].r,&g[i].t);
       g[i].id=i;
       v.push_back(g[i].t);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());//排序+去重
    build(1,v.size(),1);
    sort(g+1,g+n+m+1);
    for (int i=1;i<=n+m;i++)
    {
        int pos=get(g[i].t);
        if (g[i].id<=n)//当前为车
        {
            update(pos,g[i].id,g[i].r,1);
        }
        else//当前为人
        {
            ans[g[i].id-n]=query(pos,g[i].r,1);
        }
    }
    for (int i=1;i<=m;i++)
    {
        printf("%d ",ans[i]);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值