hihocoder1831 80 Days

思路:

令p[i] = a[i] - b[i],p[i + n] = p[i](i = 1,2,...,n),则需要找出一段长度为n的连续序列使此序列的任一前缀和均大于-c。转化如下:首先求序列p的前缀和sum[i](i = 1,2,...,2 * n - 1),然后对i = 1,2,...,n,检查是否sum[i]...sum[i + n - 1]中的每个数均大于或等于sum[i - 1] - c即可。可以使用单调队列预处理n - 1个区间最小值。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int MAXN = 1000005;
 5 ll a[MAXN * 2], q[MAXN * 2], minn[MAXN], sum[MAXN * 2];
 6 int main()
 7 {
 8     ios::sync_with_stdio(false);
 9     int T, n;
10     ll c;
11     cin >> T;
12     while (T--)
13     {
14         memset(q, 0, sizeof q);
15         memset(minn, 0, sizeof minn);
16         memset(sum, 0, sizeof sum);
17         cin >> n >> c;
18         ll x;
19         for (int i = 1; i <= n; i++) cin >> a[i];
20         for (int i = 1; i <= n; i++)
21         {
22             cin >> x;
23             a[i] -= x;
24             a[i + n] = a[i];
25         }
26         for (int i = 1; i <= 2 * n - 1; i++) sum[i] = sum[i - 1] + a[i];
27         int front = 1, back = 1;
28         q[front] = 1;
29         for (int i = 1; i <= 2 * n - 1; i++)
30         {
31             while (sum[i] <= sum[q[back]] && back >= front)
32                 back--;
33             q[++back] = i;
34             while (q[front] <= i - n && front < back)
35                 front++;
36             if (i >= n) minn[i - n + 1] = sum[q[front]];
37         }
38         int i = 1;
39         for ( ; i <= n; i++)
40         {
41             if (minn[i] >= sum[i - 1] - c) break;
42         }
43         cout << (i == n + 1 ? -1 : i) << endl;
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/wangyiming/p/9740435.html