题目传送门
题意:一个公共三轮车车站可以提供给一些人租车,但是在开始时刻,公园里有所少量车这个是不确定的,然后现在有n个信息和q个询问,信息有两种形式+ a b代表在a时间有b个人还车,另外一种是 - a b代表在a时间有b个人借车,这些人借车是要排队的,如果当前没有车,则只能等待,对于每一个询问给定了初始时刻车站里面有多少量车,然后要询问的是对于每一个可能的初始值的等待时间,如果等待时间是不确定的话,输出INFINITY。
思路:用扫描法的思想,用前面的状态来维护后面的状态防止对一些已经知道的状态进行重复的计算从而降低时间复杂度。
#include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <fstream> #include <iostream> #include <list> #include <map> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <vector> #define MAXN 100010 #define MAXE 210 #define INF 100000000 #define MOD 1000000007 #define LL long long #define pi acos(-1.0) using namespace std; LL s[MAXN]; LL t[MAXN]; LL arr[MAXN]; LL sum[MAXN]; LL anw[MAXN]; struct Node { int num; int id; }p[MAXN]; bool cmp1(const Node &x1, const Node &x2) { return x1.num < x2.num; } bool cmp2(int i, int j) { return sum[i] > sum[j]; } int main() { std::ios::sync_with_stdio(false); freopen("expect.in", "r", stdin); freopen("expect.out", "w", stdout); int n, m; while (cin >> n >> m) { string str; for (int i = 1; i <= n; ++i) { cin >> str >> t[i] >> s[i]; if (str == "-") { s[i] = -s[i]; } } for(int i = 1; i <= n; i++){ sum[i] = sum[i - 1] + s[i]; if(i < n) t[i] = t[i + 1] - t[i]; } LL sum1 = 0, sum2 = 0; int cnt = 0; for (int i = 1; i <= n; ++i) { if (sum[i] < 0) { arr[++cnt] = i; sum1 += (-sum[i]) * t[i]; sum2 += t[i]; } } for (int i = 1; i <= m; ++i) { cin >> p[i].num; p[i].id = i; } int pos = 1; sort(arr + 1, arr + cnt + 1, cmp2); sort(p + 1, p + 1 + m, cmp1); for (int i = 1; i <= m; ++i) { LL num = p[i].num; while (pos <= cnt && (-sum[arr[pos]]) <= num) { sum1 -= (-sum[arr[pos]]) * t[arr[pos]]; sum2 -= t[arr[pos]]; pos++; } if (sum[n] + num < 0) { anw[p[i].id] = -1; } else { anw[p[i].id] = sum1 - num * sum2; } } for (int i = 1; i <= m; ++i) { if (anw[i] == -1) { cout << "INFINITY\n"; } else { cout << anw[i] << endl; } } } return 0; } /* 5 4 - 1 1 - 2 2 + 4 1 - 6 1 + 7 2 0 3 1 2 */