只要相差k天,然后来的航班取个小的,去的航班取个小的就是答案;
先维护去的航班第p天开始能使所有地点都能到达的最小值,拿线段树维护最小值,然后枚举来的航班得出答案。
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson num<<1,Left,Mid
#define rson num<<1|1, Mid+1, Right
typedef long long LL;
const LL INF = 1e18;
const int Maxn = 1e5 + 10;
struct asd{
int d, f;
LL w;
}node1[Maxn], node2[Maxn];
bool cmp(asd x, asd y){return x.d < y.d;}
int num1, num2;
LL s[Maxn*10], f[Maxn*10];
int n, m, k;
struct Seg{
int Left, Right;
LL Mi;
}node[Maxn*50];
void Build(int num, int Left, int Right){
node[num].Left = Left;
node[num].Right = Right;
if(Left == Right){
node[num].Mi = INF;
return;
}
int Mid = (Left+Right)>>1;
Build(lson);
Build(rson);
node[num].Mi = INF;
}
void Update(int num, int x, LL val){
if(node[num].Left == node[num].Right){
if(node[num].Left == x) node[num].Mi = min(node[num].Mi, val);
return;
}
int Mid = (node[num].Left + node[num].Right) >> 1;
if(Mid >= x) Update(num<<1, x, val);
else Update(num<<1|1, x, val);
node[num].Mi = min(node[num<<1].Mi, node[num<<1|1].Mi);
}
LL Query(int num, int s, int t){
if(node[num].Left >= s && node[num].Right <= t)
return node[num].Mi;
int Mid = (node[num].Left + node[num].Right) >> 1;
if(Mid >= t) return Query(num<<1, s, t);
else if(Mid < s) return Query(num<<1|1, s, t);
else return min(Query(num<<1, s, Mid), Query(num<<1|1, Mid+1, t));
}
int main(){
int dd, ss, ff;
LL ww;
for(int i=1;i<=1000000;i++) s[i] = f[i] = -1;
scanf("%d%d%d",&n,&m,&k);
num1 = num2 = 0;
for(int i=0;i<m;i++){
scanf("%d%d%d%I64d",&dd,&ss,&ff,&ww);
if(!ss){
node2[num2] = (asd){dd, ff, ww};
num2++;
}
else{
node1[num1] = (asd){dd, ss, ww};
num1++;
}
}
sort(node1, node1+num1, cmp);
sort(node2, node2+num2, cmp);
Build(1, 1, 1000000);
int Left = 0, Right = num2 - 1;
int Left_num = 0, Right_num = 0;
LL ans = 0;
while(Right >= 0){
if(f[node2[Right].f] == -1){
f[node2[Right].f] = node2[Right].w;
Right_num++;
ans = ans + f[node2[Right].f];
}
else if(node2[Right].w < f[node2[Right].f]){
ans = ans - f[node2[Right].f];
f[node2[Right].f] = node2[Right].w;
ans = ans + f[node2[Right].f];
}
if(Right_num == n) Update(1, node2[Right].d, ans);
Right--;
}
ans = 0;
LL res = INF, temp;
while(Left < num1){
if(s[node1[Left].f] == -1){
s[node1[Left].f] = node1[Left].w;
Left_num++;
ans = ans + s[node1[Left].f];
}
else if(node1[Left].w < s[node1[Left].f]){
ans = ans - s[node1[Left].f];
s[node1[Left].f] = node1[Left].w;
ans = ans + s[node1[Left].f];
}
if(Left_num == n){
if((node1[Left].d + k + 1) < 1000000) temp = Query(1, node1[Left].d + k + 1, 1000000);
if(temp != INF) res = min(ans + temp, res);
}
Left++;
}
if(res == INF) puts("-1");
else printf("%I64d\n", res);
return 0;
}