【链接】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; }