1 条题解
-
0
考虑断环成链,然后求出每个位置左边第一个比他小的数的位置 和右边第一个不超过他的数的位置 ,这里可以使用单调栈。
显然第 个位置对失去牛奶的贡献就是在 这几秒中,失去一个初始值和公差都是 的等差数列,然后在之后的所有时间失去等差数列的末项个单位的牛奶。
这是一个经典 trick,使用差分数组的差分维护即可,实现细节见参考代码。时间复杂度 。
参考代码:
#include<bits/stdc++.h> #define int long long using namespace std; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)){ x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return x * f; } int n, a[1000005], l[1000005], r[1000005], d[1000005], sum = 0; signed main(){ n = read(); for(int i = 1; i <= n; i++) sum += (a[i] = a[i + n] = read()); stack<int> s; for(int i = 1; i <= n + n; i++){ while(!s.empty() && a[s.top()] >= a[i]) s.pop(); l[i] = s.empty() ? 0 : s.top(); s.push(i); } while(!s.empty()) s.pop(); for(int i = n + n; i >= 1; i--){ while(!s.empty() && a[s.top()] > a[i]) s.pop(); r[i] = s.empty() ? n + 1 : s.top(); s.push(i); } int Minid = 0; a[0] = INT_MAX; for(int i = 1; i <= n; i++) if(a[i] < a[Minid]) Minid = i; // for(int i = Minid + 1; i <= Minid + n; i++) cout << l[i] << ' ' << r[i] << '\n'; for(int i = Minid + 1; i <= Minid + n; i++) if(a[i] > a[Minid]){ int L = 1, R = r[i] - l[i] - 1; int A = a[i] - max(a[l[i]], a[r[i]]), D = A; // cout << i << ": " << L << ' ' << R << ' ' << A << '\n'; d[L] += A, d[L + 1] += D - A, d[R + 1] -= D; } for(int i = 1; i <= n; i++) d[i] += d[i - 1]; for(int i = 1; i <= n; i++) cout << sum - (d[i] += d[i - 1]) << '\n'; return 0; }
- 1
信息
- ID
- 7614
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 14
- 已通过
- 6
- 上传者