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

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
这是第二次遇到把你开始的条件和查询一起保存起来,然后再来操作的题目。
题意:有n辆公交车,知道每一辆公交车的起始车站,终止车站,还有起始时间。有m个人,知道每一个人的起始车站,终止车站,以及起始时间。问吗,每一个人符合条件的公交车车牌号是多少(到起始时间最早)。
首先时间是1e9,所以要用离散化离散一下。对于每一辆公交车,每一个人都有起始车站,终止车站,起始时间。我们将n+m个数据存起来,然后按着起始时间排序,那么排在后面的数据,起始车站一定小于前面的,那么我们只考虑终止车站就好了。如果是1~n,按着时间在权值线段树上插入点,权值线段树上维护终止车站的最大值。如果是n+1 ~m+n,那么就直接在权值线段树上查询最符合条件的车牌号。
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

const int maxx=1e5+100;
struct node{
	int l;
	int r;
	int sum;
	int id;
}p[maxx<<3];
struct Node{
	int l;
	int r;
	int t;
	int id;
	bool operator <(const Node &a)const{
		if(a.l!=l) return a.l>l;
		else return a.id>id;
	}
}t[maxx<<1];
int a[maxx<<1],ans[maxx];
int n,m;

inline void pushup(int cur)
{
	p[cur].sum=max(p[cur<<1].sum,p[cur<<1|1].sum);
}
inline void build(int l,int r,int cur)
{
	p[cur].l=l;
	p[cur].r=r;
	p[cur].id=-1;
	p[cur].sum=-inf;
	if(l==r) return ;
	int mid=l+r>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
}
inline void update(int pos,int r,int id,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(L==R)
	{
		p[cur].sum=r;
		p[cur].id=id;
		return ;
	}
	int mid=L+R>>1;
	if(pos<=mid) update(pos,r,id,cur<<1);
	else update(pos,r,id,cur<<1|1);
	pushup(cur);
}
inline int query(int pos,int r,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	//if(p[cur].sum<r) return -1;
	if(L==R)//到达叶子节点后
	{
		if(p[cur].sum>=r) return p[cur].id;
		else return -1;
	}
	int mid=L+R>>1;
	if(pos<=mid)//如果小于中间值
	{
		int ans=-1;
		if(r<=p[cur<<1].sum) ans=query(pos,r,cur<<1);//左子树可能有符合条件的车辆
		if(ans==-1) ans=query(pos,r,cur<<1|1);//在左子树没有找到,那么就去右子树查找
		return ans;
	}
	return query(pos,r,cur<<1|1);//大于中间值的话就直接去右子树查找就好了
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n+m;i++)
		{
			scanf("%d%d%d",&t[i].l,&t[i].r,&t[i].t);
			t[i].id=i;
			a[i]=t[i].t;
		}
		sort(a+1,a+1+n+m);
		int len=unique(a+1,a+1+n+m)-a-1;//离散化
		build(1,len,1);
		sort(t+1,t+1+n+m);
		for(int i=1;i<=n+m;i++)
		{
			if(t[i].id<=n) update(lower_bound(a+1,a+1+len,t[i].t)-a,t[i].r,t[i].id,1);
			else ans[t[i].id-n]=query(lower_bound(a+1,a+1+len,t[i].t)-a,t[i].r,1);
		}
		for(int i=1;i<=m;i++) printf("%d ",ans[i]);
		puts("");
	}
	return 0;
}

努力加油a啊,(o)/~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值