Codeforces 160E Buses and People【二分+线段树+离散化】

142 篇文章 0 订阅
46 篇文章 0 订阅

E. Buses and People
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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 sito 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 ≤ liri ≤ 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: sifiti (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: liribi (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

题目大意:


给出N个车的起点站,终点站和始发时间,再给出M个人的起点站,终点站,和到达起点站的时间。

如果一个车经过并且能够让这个人到达终点站,他就会上车(也就是说,他上的车是始发时间最小的那辆)

保证车的始发时间都不同。

问一个人能否到达目的地,如果可以,输出他上的车的编号。


思路:


①题干也给出了,假设我们此时人的起点站和终点站是【l,r】,我们要找的问题其实就是找一个车的区间【L,R】使得这个车的区间要:L<=l&&r<=R.并且这个车的始发时间要大于这个人的到达时间。而且希望我们找到的这辆车的t最小。


②那么我们首先将【l,r】以及【L,R】都按照l从小到大排序,那么对应我们在查询的时候就可以忽略掉一个元素。


③然后我们在建立一颗线段树,树上第i个点表示时刻为i的车的R的值。

那么我们对应这里需要离散化一下。

然后问题就变成了:

在一个区间【L,R】找一个pos,使得这个pos是最最左边满足val【pos】>=query的位子。(这里L表示当前查询这个人的时间点,R表示最大的时间点) 

那么过程我们二分一下就好,每次找到中点mid,查询【L,mid】是否扔大于等于query即可。

过程维护一下最优解,输出就行。


这样做常数很大,而且时间复杂度是O(n(logn)^2)的,TLE了两发,卡着CF机子998ms过了= =之后应该学一发nlogn的做法。




Ac代码:

#include<stdio.h>
#include<algorithm>
#include<map>
#include<string.h>
using namespace std;
map<int,int>s;
map<int,int>rs;
struct node
{
    int l,r,t,pos;
} a[250000],b[2500000];
int c[2500000];
int n,m;
int cmp(node a,node b)
{
    return a.l<b.l;
}
void init()
{
    s.clear();
    rs.clear();
    int cnt=0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].t);
        a[i].pos=i;
        c[cnt++]=a[i].t;
    }
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].t);
        b[i].pos=i;
        c[cnt++]=b[i].t;
    }
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+m,cmp);
    int tot=0;
    sort(c,c+cnt);
    for(int i=0; i<cnt; i++)if(s[c[i]]==0)s[c[i]]=++tot;
    for(int i=1;i<=n;i++)
    {
        rs[s[a[i].t]]=a[i].pos;
    }
}
/***************************/
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[300400*4];
void pushup(int rt)
{
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return tree[rt];
    }
    else
    {
        int m=(l+r)>>1;
        int ans=0;
        if(L<=m)
        {
            ans=max(query(L,R,lson),ans);
        }
        if(m<R)
        {
            ans=max(query(L,R,rson),ans);
        }
        return ans;
    }
}
void build( int l ,int r , int rt )
{
    if( l == r )
    {
        tree[rt]=0;
        return ;
    }
    else
    {
        int m = (l+r)>>1 ;
        build(lson) ;
        build(rson) ;
        pushup(rt) ;
    }
}
void update(int p,int c,int l,int r,int rt)//p阵营c数据.
{
    if(l==r)
    {
        tree[rt]=max(tree[rt],c);
    }
    else
    {
        int m=(l+r)>>1;
        if(p<=m) update(p,c,lson);
        else  update(p,c,rson);
        pushup(rt);
    }
}
/***************************/
int output[3500000];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init();
        int j=1;
        build(1,200000,1);
        for(int i=1;i<=m;i++)
        {
            while(j<=n&&a[j].l<=b[i].l)
            {
                update(s[a[j].t],a[j].r,1,200000,1);
                j++;
            }
            if(query(s[b[i].t],200000,1,200000,1)>=b[i].r)
            {
                int ans=0x3f3f3f3f;
                int l=s[b[i].t];
                int r=200000;
                while(r-l>=0)
                {
                    int mid=(l+r)/2;
                    if(query(s[b[i].t],mid,1,200000,1)<b[i].r)                    {
                        l=mid+1;
                    }
                    else
                    {
                        r=mid-1;
                        ans=min(ans,mid);
                    }
                }
                output[b[i].pos]=rs[ans];
            }
            else output[b[i].pos]=-1;
        }
        for(int i=1;i<=m;i++)printf("%d ",output[i]);
        printf("\n");
    }
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值