对于 30% 的数据,n ≤ 3000;
对于另外 20% 的数据,数列 a 为随机生成;
对于 100% 的数据,1 ≤ n ≤ 3 × 10^5 , 1 ≤ k ≤ 10^6 , 1 ≤ ai ≤ 10^9。
这似乎是loj #6463的序列上问题的弱化……即一类分治套路题……
设当前处理$[l,r]$,处理完$[l,mid]$和$[mid+1,r]$之后,处理跨过$mid,mid+1$的区间的贡献
开一个$cnt$数组,双指针扫两遍就行了
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e6 + 10; 4 typedef long long ll; 5 int n, k, a[N]; 6 ll s[N], ans, cnt[N]; 7 void sol(int ql, int qr) { 8 if(ql == qr) { 9 return ; 10 } else { 11 int mid = (ql + qr) >> 1; 12 sol(ql, mid), sol(mid + 1, qr); 13 int l, r, mxl, mxr; ll sl, sr, sum; 14 l = mid, r = mid + 1, mxl = a[l], mxr = a[r]; 15 sl = 0, sr = a[r] % k; 16 ++ cnt[sr]; 17 while(l >= ql) { 18 mxl = max(mxl, a[l]); 19 sl = (sl + a[l]) % k; 20 while(r + 1 <= qr && mxl >= max(mxr, a[r + 1])) { 21 ++ r; 22 mxr = max(mxr, a[r]); 23 sr = (sr + a[r]) % k; 24 ++ cnt[sr]; 25 } 26 if(mxl >= mxr) { 27 ll qu = -sl + mxl; 28 qu = (qu % k + k) % k; 29 ans += cnt[qu]; 30 } 31 -- l; 32 } 33 sum = 0; for(int i = mid + 1 ; i <= qr ; ++ i) cnt[sum = (sum + a[i]) % k] = 0; 34 l = mid, r = mid + 1, mxl = a[l], mxr = a[r]; 35 sl = a[l] % k, sr = 0; 36 ++ cnt[sl]; 37 while(r <= qr) { 38 mxr = max(mxr, a[r]); 39 sr = (sr + a[r]) % k; 40 while(l - 1 >= ql && mxr > max(mxl, a[l - 1])) { 41 -- l; 42 mxl = max(mxl, a[l]); 43 sl = (sl + a[l]) % k; 44 ++ cnt[sl]; 45 } 46 if(mxr > mxl) { 47 ll qu = -sr + mxr; 48 qu = (qu % k + k) % k; 49 ans += cnt[qu]; 50 } 51 ++ r; 52 } 53 sum = 0; for(int i = mid ; i >= ql ; -- i) cnt[sum = (sum + a[i]) % k] = 0; 54 } 55 } 56 int main() { 57 freopen("interval.in", "r", stdin); 58 freopen("interval.out", "w", stdout); 59 scanf("%d%d", &n, &k); 60 for(int i = 1 ; i <= n ; ++ i) scanf("%lld", &a[i]); 61 sol(1, n); 62 printf("%lld\n", ans); 63 }