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】简单的区间

转载于:https://www.cnblogs.com/KingSann/articles/9469655.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值