#442 Div2 F

题意

给出一些包含两种类型(a, b)问题的问题册,每本问题册有一些题目,每次查询某一区间,问有多少子区间中 a 问题的数量等于 b 问题的数量加 \(k\) 。

分析

令包含 a 问题的问题册的问题数取正值,包含 b 问题的问题册的问题数取负值,那么问题就是求有多少子区间的和为 \(k\) 。

先求前缀和,记录 \(i\) 出现的次数 \(cnt[i]\)。当计算完前缀和 \(b[i-1]\) 后,考虑前缀和 \(b[i]\) ,\(cnt[b[i]-k]\)为对答案的贡献。

对于这种多个区间的询问,且区间从 \([L,R]\) 到 \([L,R+1]\) 或 \([L-1,R]\) 只需要 \(O(1)\) 的复杂度时,可以用莫队算法去优化,离线 + 分块。

注意,并不能直接用数组去存 \(cnt\) ,用 \(map\) 也会超时,这里可以离散化掉所有可能的值,因为我们只关心某种数字出现的次数。

code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 1e5 + 10;
const int BLOCK = 300;
int n, k;
ll a[MAXN], b[MAXN];
ll s[MAXN << 2];
int x[MAXN], y[MAXN], z[MAXN];
ll O[MAXN << 2];
struct P {
int l, r, b, i;
bool operator < (const P& o) const {
if(b != o.b) return b < o.b;
return r < o.r;
}
}p[MAXN];
ll ans[MAXN];
int main() {
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++) {
scanf("%lld", &a[i]);
if(a[i] != 1) a[i] = -1;
}
for(int i = 0; i < n; i++) {
scanf("%lld", &b[i]);
if(!i) b[i] = a[i] * b[i];
else b[i] = b[i - 1] + a[i] * b[i];
}
int c = 0;
b[n] = 0;
for(int i = 0; i <= n; i++) {
s[c++] = b[i];
s[c++] = b[i] + k;
s[c++] = b[i] - k;
}
sort(s, s + c);
int cc = unique(s, s + c) - s;
for(int i = 0; i <= n; i++) {
x[i] = lower_bound(s, s + cc, b[i] - k) - s;
y[i] = lower_bound(s, s + cc, b[i]) - s;
z[i] = lower_bound(s, s + cc, b[i] + k) - s;
}
int q;
scanf("%d", &q);
for(int i = 0; i < q; i++) {
scanf("%d%d", &p[i].l, &p[i].r);
p[i].l--;
p[i].r--;
p[i].b = p[i].l / BLOCK;
p[i].i = i;
}
sort(p, p + q);
int L = 0, R = 0;
ll res = 0;
for(int i = 0; i < q; i++) {
int l = p[i].l, r = p[i].r;
if(!i) {
if(l == 0) O[y[n]]++;
else O[y[l - 1]]++;
for(int j = l; j <= r; j++) {
res += O[x[j]];
O[y[j]]++;
}
} else {
for(int j = R + 1; j <= r; j++) {
res += O[x[j]];
O[y[j]]++;
}
for(int j = L - 1; j >= l; j--) {
if(j == 0) { res += O[z[n]]; O[y[n]]++; }
else { res += O[z[j - 1]]; O[y[j - 1]]++; }
}
for(int j = R; j > r; j--) {
O[y[j]]--;
res -= O[x[j]];
}
for(int j = L; j < l; j++) {
if(j == 0) { O[y[n]]--; res -= O[z[n]]; }
else { O[y[j - 1]]--; res -= O[z[j - 1]]; }
}
}
L = l;
R = r;
ans[p[i].i] = res;
}
for(int i = 0; i < q; i++) printf("%lld\n", ans[i]);
return 0;
}

最新文章

  1. PHP 设计模式概述
  2. tableview左滑按钮 tableviewcell自定义左滑按钮
  3. 如何在Ubuntu下安装”.deb“、”.bin“、”.tar.gz“、”.tar.bz2“格式的软件包!
  4. html5表单新特性
  5. jquery Deferred demo
  6. 为MYPoint类写一个分类
  7. 关于MySQL Connector/C++那点事儿
  8. Java依据Url下载图片
  9. 基于 HTML5 Canvas 的简易 2D 3D 编辑器
  10. AI - TensorFlow - 分类与回归(Classification vs Regression)
  11. Clickhouse v18编译记录
  12. 11、jeecg 笔记之 界面常用整理 - 方便复制粘贴
  13. zabbix监控实战&lt;3&gt; 之自定义监控实例
  14. 兼容ie8的前端下载方法
  15. CentOS7用yum快速搭建LAMP平台
  16. leetcode 388.Lonest Absolute File Path
  17. Python加密与解密
  18. 【Java并发编程】21、线程池ThreadPoolExecutor源码解析
  19. 【转载】谈谈自己对REST、SOA、SOAP、RPC、ICE、ESB、BPM知识汇总及理解
  20. react查缺补漏01

热门文章

  1. DataBase -- FUNCTION
  2. [Leetcode] Anagrams 颠倒字母构成词
  3. fail2ban软件 +ssh密钥登录
  4. 深入理解Java虚拟机—内存管理机制
  5. 【可持久化线段树?!】rope史上最全详解
  6. codeforces 1077D
  7. hive连接数
  8. Eclipse中的Web项目自动部署到Tomcat的webapp目录下
  9. C# Producer Consumer (生产者消费者模式)demo
  10. 【BZOJ】1770 [Usaco2009 Nov]lights 燈