Range Add Query
题目描述:
You are given an integer sequence of length \(N\), \(A=(A_1 ,A_2 ,…,A_N)\), and a positive integer \(K\).
For each \(i=1,2,…,Q\), determine whether a contiguous subsequence of \(A, (A_{l_i} ,A _{l_i+1},…,A_{r_i})\), is a good sequence.
Here, a sequence of length \(n\), \(X=(X_1,X_2,…,X_n)\), is good if and only if there is a way to perform the operation below some number of times (possibly zero) to make all elements of \(X\) equal \(0\).
- Choose an integer \(i\) such that \(1≤i≤n−K+1\) and an integer \(c\) (possibly negative). Add \(c\) to each of the \(K\) elements \(X_i ,X_{i+1} ,…,X_{i+K−1}\).
It is guaranteed that \(r_i −l_i +1≥K\) for every \(i=1,2,…,Q\).
- \(1≤N≤2×10^5\)
- \(1≤K≤min\begin{Bmatrix}10, N\end{Bmatrix}\)
- \(−10^9 ≤A_i ≤10^9\)
- \(1≤Q≤2×10^5\)
- \(1≤l_i ,r_i ≤ N\)
- \(r_i −l_i+1≥K\)
- All values in the input are integers.
输入描述:
\( N K \)
\( A_1 A_2 ... A_N \)
\( Q \)
\( l_1 r_1\)
\( l_2 r_2 \)
\( ⋮ \)
\( l _Q r_Q \)
输出描述:
Print \(Q\) lines. For each \(i=1,2,…,Q\), the \(i\)-th line should contain Yes if the sequence \((A_{l_i} ,A_{l_{i+1}} ,…,A_{r_i})\) is good, and No otherwise.
样例1:
input:
7 3
3 -1 1 -2 2 0 5
2
1 6
2 7
output:
Yes
No
The sequence \(X:=(A_1 ,A_2,A_3 ,A_4 ,A_5 ,A_6 )=(3,−1,1,−2,2,0)\) is good. Indeed, you can do the following to make all elements equal \(0\).
-
First, do the operation with \(i=2,c=4\), making \(X=(3,3,5,2,2,0)\).
-
Next, do the operation with \(i=3,c=−2\), making \(X=(3,3,3,0,0,0)\).
-
Finally, do the operation with \(i=1,c=−3\), making \(X=(0,0,0,0,0,0)\).
Thus, the first line should contain Yes.
On the other hand, for the sequence \((A_2 ,A_3 ,A_4 ,A_5 ,A_6 ,A_7 )=(−1,1,−2,2,0,5)\), there is no way to make all elements equal \(0\), so it is not a good sequence. Thus, the second line should contain No.
样例2:
input:
20 4
-19 -66 -99 16 18 33 32 28 26 11 12 0 -16 4 21 21 37 17 55 -19
5
13 16
4 11
3 12
13 18
4 10
output:
No
Yes
No
Yes
No
AC代码:
#include <bits/stdc++.h>
using namespace std;
// 这个题可以通过一般形式来找规律
// 假设K = 3,有七个数A, B, C, D, E, F, G
// 假设N = 3,因为要让所有数都变为0,所以可以先让A变为0
// 所以操作后就变成0,B - A, C - A, 若是一个good数组,则此时B - A = 0 = C - A,得A = B = C
// 假设N = 4,一次操作后为0, B - A, C - A, D,第二次操作后为0, 0, C - B, A + D - B
// 此时可得C - B = 0 = A + D - B,即A + D = B = C
// 同理可得N = 5时,A + D = C = B + E
// 通过观察不难发现只要对于N个数,其不同下标i对K取模相等的数的和相同,那么就可以是一个good数组
// 或者不用找规律的方式来想
// 依旧是从前往后依次操作,如果是good数组,那么最后肯定会全是0,否则最后肯定会有某些数不是0
// 可以发现每次操作都会将下标对K取模为0 ~ K - 1这K个数大小同时改变,且改变的数值大小相同
// 那么也就是说不同下标i对K取模相等的数的和的大小也是同时发生改变,且改变数值大小相同
// 所以在最后一次操作的过程中,如果是good数组,那么最后所有数都变成0,和也变成0
// 如果最后某些数不是0,那么这些数的坐标i对K取模相等的数的和也不会是0
// 那么根据第16行分析可知,只有可能是因为和的大小和其他和的大小不同导致的
// 所有可得必须是下标i对K取模相等的数的和全相等,才会是good数组
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, k, q;
cin >> n >> k;
vector<int> a(n);
for(int i = 0; i < n; i ++)
{
cin >> a[i];
// 运用前缀和,将对K取模相等的加起来
if(i >= k)
a[i] += a[i - k];
}
cin >> q;
while(q --)
{
int l, r;
cin >> l >> r;
l --, r --;
vector<int> b(k);
for(int i = r; r - i + 1 <= k; i --)
b[i % k] = a[i];
// 减去区间之外的
for(int i = l - 1; i >= 0 && l - i <= k; i --)
b[i % k] -= a[i];
// 只有k个数,且这k个数都(与b[0])相等
if(b == vector<int> (k, b[0]))
cout << "Yes\n";
else
cout << "No\n";
}
return 0;
}