思路:
令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 }