首先发现答案满足二分性质(并不是要去二分QAQ),所以可以排个序然后扫一遍;而且答案只和最后一辆车直接相关,因此需要得到赶上每一辆车i的最晚出发时间g[i]。
那么要先得到每一个点i,到达点i的最晚出发时间f[i],然后就可以用g[]和f[]互相更新,最后得到所有右端点=n的g[]排序之后更新答案即可。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 100005
using namespace std;
int n,m,pt,cnt,f[N],g[N<<2],ans[N]; struct edg{ int x,y,s,t; }e[N<<2]; struct node{ int x,y; }a[N],c[N<<2];
priority_queue<node,vector<node>,greater<node> > q;
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
bool cmp(edg u,edg v){ return u.s<v.s; }
bool operator <(node u,node v){ return u.x<v.x; }
bool operator >(node u,node v){ return u.x>v.x; }
int main(){
n=read(); m=read(); int i; node t;
for (i=1; i<=m; i++){
e[i].x=read(); e[i].y=read(); e[i].s=read(); e[i].t=read();
}
sort(e+1,e+m+1,cmp);
memset(f,-1,sizeof(f)); f[1]=1000000000;
for (i=1; i<=m; i++){
while (!q.empty() && q.top().x<=e[i].s){
t=q.top(); q.pop();
f[e[t.y].y]=max(f[e[t.y].y],g[t.y]);
}
g[i]=min(e[i].s,f[e[i].x]);
t.x=e[i].t; t.y=i; q.push(t);
if (e[i].y==n){
c[++cnt].x=e[i].t; c[cnt].y=g[i];
}
}
sort(c+1,c+cnt+1);
pt=read();
for (i=1; i<=pt; i++){
a[i].x=read(); a[i].y=i;
}
sort(a+1,a+pt+1); int now=-1,j=1;
for (i=1; i<=pt; i++){
for(; j<=cnt && c[j].x<=a[i].x; j++) now=max(now,c[j].y);
ans[a[i].y]=now;
}
for (i=1; i<=pt; i++) printf("%d\n",ans[i]);
return 0;
}
by lych
2016.3.25