JZOJ 5807. 【NOIP提高A组模拟2018.8.13】简单的区间

对于 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 }
JZOJ 5807. 【NOIP提高A组模拟2018.8.13】简单的区间
posted @ 2018-08-13 18:09  KingSann  阅读(259)  评论(0)    收藏  举报