Buses and People 三维处理
题目大意:有n辆公交车,每辆公交车有s(起始点),f(终点),t(发车时间) ,有m个人,每个人有l(起点),r(终点),t(出现时间)
对于一个人,当t(人)<=t(车), s<=l,r <=f 时就能上这辆车,问能上的发车时间最早的是那一辆
类似三维偏序问题,有三个维度需要我们解决。首先,车和人都有l,r,t,三个属性,先按照l排序,解决第一维,这样,对于一个人,前面的所有的车都是可能上去的。剩下的两个维度用线段树来解决,线段树维护区间最大值。线段树下标对应的是t,维护的最大值是r。把车和人在一起排序,从头遍历,是车,就在t位置插入r,是人,就在线段树t位置到末端查询满足小于r的最小的下标对应的id(也就是车的id)。
怎么也没想到可以用一个线段树直接解决两维。
查询到一个人,前面已经插入的车的l一定都比它小了;线段树查询的是t到末端,t大于人的车一定在其中;线段树维护的是r最大值,只要查询的区间内的r有大于等于此人的r,那么这个人就一定能上车。
排序解决一维,线段树解决一维,维护的最大值解决一维。
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Mid ((a[k].l+a[k].r)>>1)
#define cl (k<<1)
#define cr (k<<1|1)
#define Max 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
struct Q{
int l,r,t, id,tp;//tp==0 车, tp==1 人
friend bool operator <(Q a, Q b){
if(a.l!=b.l) return a.l < b.l; //按照l排序,若l相同,人在后
return a.tp < b.tp;
}
}q[maxn*2];
struct N{
int l,r;
int ma,id;
}a[maxn*4];
int dis[maxn*2], cur;//离散化
int ans[maxn];
void build(int k,int l,int r){
a[k].l=l, a[k].r=r;
a[k].ma = -1;
a[k].id = -1;
if(l==r) return;
int mid=Mid;
build(cl,l,mid), build(cr,mid+1,r);
}
void updata(int k,int i,int x, int id){
if(a[k].l==a[k].r){
if(a[k].ma < x){
a[k].ma = x;
a[k].id = id;
}
return;
}
int mid=Mid;
if(i<=mid) updata(cl,i,x,id);
else updata(cr,i,x,id);
if(a[k].ma < a[cl].ma){
a[k].ma = a[cl].ma;
a[k].id = a[cl].id;
}
if(a[k].ma < a[cr].ma){
a[k].ma = a[cr].ma;
a[k].id = a[cr].id;
}
}
int get(int k,int l,int r,int x){//返回符合要求的最小的下标 对应的id
if(a[k].l==a[k].r && a[k].ma>=x)
return a[k].id;
int mid=Mid;
int ret=Max;
if(l<=mid && a[cl].ma>=x ){ //若左边有符合的,可以直接返回,左边的下标(t)一定比右边小
ret = get(cl,l,r,x);
if(ret!=Max) return ret;
}
if(r>mid && a[cr].ma>=x ){
ret = get(cr,l,r,x);
if(ret!=Max) return ret;
}
return ret;
}
int gs(int x){return lower_bound(dis+1,dis+1+cur,x)-dis; }//离散化
int main()
{
int n,m,qn=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
qn++;
scanf("%d%d%d",&q[qn].l, &q[qn].r, &q[qn].t);
q[qn].tp = 0;
q[qn].id = i;
dis[++cur] = q[qn].t;
}
for(int i=1; i<=m; i++){
qn++;
scanf("%d%d%d",&q[qn].l, &q[qn].r, &q[qn].t);
q[qn].tp = 1;
q[qn].id = i;
dis[++cur] = q[qn].t;
}
sort(dis+1,dis+cur+1);
cur = unique(dis+1,dis+cur+1) - (dis+1);
sort(q+1,q+1+qn);
build(1,1,cur);
for(int i=1; i<=qn; i++){
if(q[i].tp==0){//车
updata(1, gs(q[i].t) ,q[i].r, q[i].id);
}else{
int x=get(1, gs(q[i].t), cur, q[i].r);
if(x==Max)//没找到
ans[q[i].id] = -1;
else
ans[q[i].id] = x;
}
}
for(int i=1; i<=m; i++){
printf("%d ",ans[i]);
}
printf("\n");
}