题目描述
难度分:1300
输入T(≤4×104)表示T组数据。所有数据的n之和≤2×105。
每组数据输入n(2≤n≤2×105)和长为n的数组a(1≤a[i]≤109),长为 n的数组b(1≤a[i]≤109)。
你可以执行如下操作任意次:
- 选择一个下标i,满足a[i]≤a[(i+1)%n],然后把a[i]增加1。
能否把a变成b?输出YES
或NO
。
输入样例
5
3
1 2 5
1 2 5
2
2 2
1 3
4
3 4 1 2
6 4 2 5
3
2 4 1
4 5 3
5
1 2 3 4 5
6 5 6 7 6
输出样例
YES
NO
NO
NO
YES
算法
贪心
由于只能对a数组中的元素进行自增操作,因此如果存在a[i]>b[i]的下标i,肯定就无解了。而a[i]=b[i]的下标不用管,所以只需要去考虑a[i]<b[i]的下标。
而a[i]要想变成b[i],那a[i+1]至少就要是b[i]−1,因此我们检查b[i]−1会不会超过b[i+1]就行了。如果超过了,说明a[i+1]要变成一个大于b[i+1]的数才能使得a[i]变成b[i],但a[i+1]就永远不可能变成b[i+1]了。(以上讨论中,当i=n时,满足i+1=1)
综上,当b[i]−1≤b[i+1]对所有i∈[1,n]都成立时答案是YES
,否则答案就是NO
。
复杂度分析
时间复杂度
对于每个case,只遍历了一遍数组就求出了答案,因此算法的时间复杂度为O(n)。
空间复杂度
除了输入的a和b两个数组,只使用了有限几个变量,因此算法的额外空间复杂度为O(1)。
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
int T, n, a[N], b[N];
bool solve() {
for(int i = 1; i <= n; i++) {
if(a[i] < b[i]) {
// a[i]要变成b[i],说明a[i+1]至少要为b[i]-1
if(i < n) {
if(b[i] - 1 > b[i + 1]) return false;
}else {
if(b[i] - 1 > b[1]) return false;
}
}else if(a[i] > b[i]) {
return false;
}
}
return true;
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
}
if(solve()) {
puts("YES");
}else {
puts("NO");
}
}
return 0;
}