【链接】h在这里写链接
【题意】
有n个人,它们都要在某一时刻开始,全都到达0位置,然后维持最少k个时间单位,然后再全都回到原来的位置;
第i个人初始的位置是i.
且一共有m班航班.
每一班航班,要么是从0出来的,要么是进入0的,且航班起飞的时间为di,出发地为fi,目的地为ti,花费为ci;
(航班当天到);
到或起飞的那一天不算k天中的一天。
问你每个人到达0,然后又回到各自位置的最小花费。
【题解】
考虑每个航班起飞的时间,把每个航班的信息加入到di时刻上.
vector <pair <int,int> >in[N];
存的是i时刻,进入0位置的飞机来自哪里,以及花费。
vector <pair <int,int> >out[N];
存的是i时刻,飞出0位置的飞机要到哪里,以及花费。
然后O(N)顺着扫和逆着扫两遍。
就能得到f1[i],num1[i];
f1[i]表示前i个位置,有num1[i]个人能到0位置,最小的花费是多少.
(时间顺序处理)
以及f2[i],num2[i];
f2[i]表示后n-i+1个位置,有num2[i]个人能回到原位置,最小的花费是多少;
(时间逆序处理就好)
以处理f1[i]为例。
进入i+1时刻的时候,看看i+1这个时间,有多少个航班到位置0,然后,看看某个人来0位置的花费能不能因此变少。
(也即是不是那个人坐这班航班更优)
如果可以因此变少的话,f1[i]也能变少.
(如果那个人是第一次可以来0位置,那么num1[i]++)
用一个mi[N]来维护某个人到达0位置的最小花费就可以了。
(f2[i]用类似的方法维护就好)
然后枚举这n个人是何时开始全都到达0号位置的。
取f1[i]+f2[i+k+1]最小值就可以了;
(num1[i]和num2[i+k+1]都必须为n);
【错的次数】
0
【反思】
感觉很自然的思路。
【代码】
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6;
int n, m, k;
vector <pair <int, int > > in[N + 10], out[N + 10];
long long f1[N + 10], f2[N + 10];
int num1[N + 10], num2[N + 10];
int mi[N + 10], MI[N + 10];
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int d, f, t, c;
cin >> d >> f >> t >> c;
if (t == 0)
in[d].push_back(make_pair(f, c));
else {
//f == 0
out[d].push_back(make_pair(t, c));
}
}
for (int i = 1; i <= N; i++) {
num1[i] = num1[i - 1];
f1[i] = f1[i - 1];
for (int j = 0; j <= (int)in[i].size() - 1; j++) {
int from = in[i][j].first, cost = in[i][j].second;
if (mi[from] == 0) {
mi[from] = cost;
num1[i]++;
f1[i] += cost;
}
else {
if (mi[from] > cost) {
f1[i] -= (mi[from] - cost);
mi[from] = cost;
}
}
}
}
for (int i = N; i >= 1; i--) {
f2[i] = f2[i + 1];
num2[i] = num2[i + 1];
for (int j = 0; j <= (int)out[i].size() - 1; j++){
int to = out[i][j].first; int cost = out[i][j].second;
if (MI[to] == 0) {
MI[to] = cost;
f2[i] += cost;
num2[i]++;
}
else {
if (MI[to] > cost) {
f2[i] -= (MI[to] - cost);
MI[to] = cost;
}
}
}
}
long long ans = -1;
for (int i = 1; i + k +1 <= N; i++)
if (num1[i]==n){
if (num2[i + k + 1] == n) {
long long temp = f1[i] + f2[i + k + 1];
if (ans == -1) {
ans = temp;
}
else
ans = min(ans, temp);
}
}
cout << ans << endl;
return 0;
}