题目:
[ABC288D] Range Add Query - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
大意:
一些数,选一个区间A(L~R),并再选一个区间B(长度k),这个区间B的每个数加减(加负数=减一个数)一个数,最终使得区间A全部数为0
举个例(样例)
0. 3 -1 1 -2 2 0
1. 0 -4 -2 -2 2 0 (-3)
2. 0 0 2 2 2 0 (+4)
3. 0 0 0 0 0 0 (-3)
所以最终为“Yes”(注意大小写问题)
思路:
刚开始就可以想到是差分了,因为是区间加减数,但是具体的不知道怎么做,也是想了比较久的时间的,很有意思
在解这题前得知道差分是什么(就是前缀和的逆)
然后要了解一个性质,例如有一个数列 (位:第几个数)
位1 2 3 4 5 6
值3 2 1 5 1 2
我们得让2~4的数加2,可以这样写
位1 2 3 4 5 6
值0 +2 0 0 -2 0
这样的话这个区间也算是每项加2了,因为第2位加了2,后面的会跟着加2,但是在第4位加完2,第5位得减回来,不然会超出范围
前置知识了解完就可以看思路了
最终,A数组加减一堆数,肯定全为0了(输出Yes的情况),那么B数组也会变成{-a1, 0, 0, 0.... 0}。由于我们要选长度为k的区间B,考虑加减一个数。所以每个数(A数组)可以对应一个余数(%k),来方便我们找规律,如下
A数组 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 余数 1 2 3 4 1 2 3 4 1 2 3 4 B数组 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 B最终 -a1 0 0 0 0 0 0 0 0 0 0 0
这里我们定,s[i][j]表示前i个数余数为j的差分数组的和,会发现有3种情况,区间内同余数和一定为0,肯定相同,但是还有左右端点要特判,所以分情况
情况1,当下标为i=(R+1)%k L+b[L]==0 在区间内,自然的
情况2,当下标为i==L mod k S[R][余]-s[L-1][余]==-a[L-1] 像b[1]最终为-a1一样,不过这里的位置不固定,换成a[L-1]
情况3,当下标i区间L,R内 s[R][余]-s[L-1][余]==0 在区间外没余数这个值了
具体可以看代码,里面的注释也很详细了
#include <bits/stdc++.h> using namespace std; const int N=2e5+5, M=11; int n, k, a[N], b[N], s[N][M], m, L, R; //s[i][j]:前i个数余数为j的差分数组的和 //b:差分数组 int yu(int x) //求余 例如4%3=1, 4%4=4 { return (x-1)%k+1; } int main() { scanf("%d%d", &n, &k); for (int i=1; i<=n; i++) { scanf("%d", &a[i]); b[i]=a[i]-a[i-1]; } //b最终: -a1 0 0 0 ... 0 for (int i=1; i<=n; i++) { for (int j=1; j<=k; j++) s[i][j]=s[i-1][j]; //余数相等,必然有 i=i-1 s[i][yu(i)]+=b[i]; //余数不同,加上此差分数组的数 } scanf("%d", &m); while (m--) { int flag=0; scanf("%d%d", &L, &R); for (int i=L; i<=L+k-1; i++) //遍历区间,不用全部跑,因为余数最多为L+k-1 { int j=yu(i); if (j==yu(R+1)) continue;//情况1不考虑,因为b数组都为0,在区间内无影响 if (j==yu(L)) //情况2 { if (s[R][j]-s[L-1][j]!=-a[L-1]) { flag=1; break; } } else //情况3 { if (s[R][j]-s[L-1][j]!=0) { flag=1; break; } } } if (flag==1) printf("No\n"); else printf("Yes\n"); } return 0; } /* A数组 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 余数 1 2 3 4 1 2 3 4 1 2 3 4 B数组 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 B最终 -a1 0 0 0 0 0 0 0 0 0 0 0 区间 2 10 (选2~10) 2 2 2 情况2,当下标为i==L mod k S[R][余]-s[L-1][余]==-a[L-1] 3 3 3 情况1,当下标为i=(R+1)%k L+b[L]==0 4 4 4 情况1,同上 1 1 情况3,当下标i区间L,R内 s[R][余]-s[L-1][余]==0 */
第一次写题解,有不足请指出,谢谢!
标签:int,题解,差分,a1,Range,ABC288D,数组,区间,余数 From: https://www.cnblogs.com/didiao233/p/17980826