CF877F Ann and Books

题意:

商店里有 \(n\) 本书,每本书中有 \(a_i\) 个 \(t_i=1/2\) 类问题。

\(m\) 次询问,每次询问给出一个区间,求有多少个符合下列条件的区间:

  • 这个区间是给出区间的子区间
  • 这个区间的所有书中第 \(1\) 类问题比第 \(2\) 类问题多 \(k\) 个,其中 \(k\) 在所有询问中相同。

抽象一下,也就是求 \([L, R]\) 内有多少个子区间 \([l, r]\) 满足

\[\sum_l^r a[1][i] = \sum_l^r a[2][i] + k
\]

\[s[1][r] - s[1][l - 1] = s[2][r] - s[2][l - 1] + k
\]
\[s[1][r] - s[2][r] = s[1][l - 1] - s[2][l - 1] + k
\]

令 \(v[i] = s[1][i] - s[2][i]\),将原问题转化为 \([L - 1, R]\) 内多少对 \((i, j)\) 满足

  • \(i < j\)
  • \(v[i] + k = v[j]\)

用莫队维护。

如果在现有区间左侧加入一个数 \(x\),则 \(x\) 只能作为区间左端点,答案加上当前的 \(cnt[x + k]\),删除同理。

如果在现有区间右侧加入一个数 \(x\),则 \(x\) 只能作为区间右端点,答案加上当前的 \(cnt[x - k]\),删除同理。

如果 \(k = 0\),由于自己和自己不能产生贡献,需考虑更新答案和更新 \(cnt\) 的顺序。

离散化的时候注意把 \(v - k\) 和 \(v + k\) 也放进去。

#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); ++ i)
#define per(i, a, b) for(int i = (a); i >= (b); -- i)
#define pb emplace_back
#define All(X) X.begin(), X.end()
using namespace std;
using ll = long long;
constexpr int N = 1e5 + 5, B = 300; #define c(x) ((x) / B) struct Node {
int l, r, id;
bool operator < (const Node &x) {
if(c(l) != c(x.l)) return c(l) < c(x.l);
if(c(l) & 1) return c(r) < c(x.r);
return c(r) > c(x.r);
}
} q[N]; ll n, m, k, t[N], v[N], lv[N], rv[N], b[N * 3], cnt[N * 3], idx;
ll res, ans[N]; void add(int x, int y) {
res += cnt[y], ++ cnt[x]; // 先加上贡献,再更新数值,防止 x = y,del同理
} void del(int x, int y) {
-- cnt[x], res -= cnt[y];
} int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> k;
rep(i, 1, n) cin >> t[i];
rep(i, 1, n) {
cin >> v[i];
v[i] = v[i - 1] + (t[i] == 1 ? 1 : -1) * v[i];
}
rep(i, 0, n) {
b[++ idx] = v[i];
b[++ idx] = v[i] - k;
b[++ idx] = v[i] + k;
}
sort(b + 1, b + idx + 1);
int tot = unique(b + 1, b + idx + 1) - b - 1;
rep(i, 0, n) {
lv[i] = lower_bound(b + 1, b + tot + 1, v[i] - k) - b;
rv[i] = lower_bound(b + 1, b + tot + 1, v[i] + k) - b;
v[i] = lower_bound(b + 1, b + tot + 1, v[i]) - b;
}
cin >> m;
rep(i, 1, m) cin >> q[i].l >> q[i].r, q[i].id = i;
sort(q + 1, q + m + 1); int l = 0, r = -1;
rep(i, 1, m) {
auto[L, R, id] = q[i];
-- L;
while(l < L) del(v[l], rv[l]), ++ l;
while(l > L) -- l, add(v[l], rv[l]);
while(r < R) ++ r, add(v[r], lv[r]);
while(r > R) del(v[r], lv[r]), -- r;
ans[id] = res;
}
rep(i, 1, m) cout << ans[i] << '\n';
return 0;
}

CF877F Ann and Books (分类统计贡献+普通莫队)的更多相关文章

  1. [CF877F]Ann and Books

    题目大意: 有$n(n\le10^5)$个数$w_{1\sim n}(|w_i|\le10^9)$,并给定一个数$k(|k|\le10^9)$.$q(q\le10^5)$次询问,每次询问区间$[l,r ...

  2. [Codeforces86D]Powerful array(莫队算法)

    题意:定义K[x]为元素x在区间[l,r]内出现的次数,那么它的贡献为K[x]*K[x]*x 给定一个序列,以及一些区间询问,求每个区间的贡献 算是莫队算法膜版题,不带修改的 Code #includ ...

  3. cf 442 div2 F. Ann and Books(莫队算法)

    cf 442 div2 F. Ann and Books(莫队算法) 题意: \(给出n和k,和a_i,sum_i表示前i个数的和,有q个查询[l,r]\) 每次查询区间\([l,r]内有多少对(i, ...

  4. Codeforces 877F Ann and Books 莫队

    转换成前缀和, 预处理一下然后莫队. #include<bits/stdc++.h> #define LL long long #define fi first #define se se ...

  5. D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

    D. Powerful array time limit per test seconds memory limit per test megabytes input standard input o ...

  6. Codeforces 617E XOR and Favorite Number(莫队算法)

    题目大概说给一个序列,多次询问区间异或和为k的连续子序列有多少个. 莫队算法,利用异或的性质,通过前缀和求区间和,先处理出序列各个前缀和,然后每次区间转移时维护i以及i-1前缀和为某数的个数并增加或减 ...

  7. uoj #58. 【WC2013】糖果公园(树上莫队算法+修改操作)

    [题目链接] http://uoj.ac/problem/58 [题意] 有一棵树,结点有自己的颜色,若干询问:u,v路径上的获益,并提供修改颜色的操作. 其中获益定义为Vc*W1+Vc*W2+…+V ...

  8. [bzoj4540][Hnoi2016][序列] (莫队算法+单调栈+st表)

    Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...

  9. 【HNOI2016】序列 莫队+单调栈+RMQ

    Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...

  10. BZOJ_3289_Mato的文件管理_莫队+树状数组

    BZOJ_3289_Mato的文件管理_莫队+树状数组 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号 .为了防止他人 ...

随机推荐

  1. go语言漏桶算法思路简单实现

    package main import ( "fmt" "time" ) // 桶 type LeakBucket struct { capacity int ...

  2. Java字符数组char和字符串String互相转化

    字符串转换为数组 1 String str = "123abc"; 2 char[] arr = str.toCharArray(); // char数组 3 for (int i ...

  3. 安卓AlertDialog对话面板的使用---Android开发

    1 AlertDialog.Builder builder=new AlertDialog.Builder(this); 2 builder.setTitle("历史记录").se ...

  4. #最小生成树,Trie#CF888G Xor-MST

    题目 给定 \(n\) 个结点的无向完全图.每个点有一个点权为 \(a_i\) . 连接 \(i\) 号结点和 \(j\) 号结点的边的边权为 \(a_i\oplus a_j\) . 求这个图的 MS ...

  5. 深度剖析 Spring 框架在 Java 应用开发中的优势与应用

    Spring 是用于企业 Java 应用程序开发的最流行的应用程序开发框架.全球数百万开发人员使用 Spring Framework 创建高性能.易于测试和可重用的代码.Spring Framewor ...

  6. Python设计模式----3.单例模式

    单例模式:主要目的是确保某一个类只有一个实例存在 代码: class A(): def __new__(self, *args, **kwargs): if not hasattr(self, 'na ...

  7. openGauss3.1.0 版本的gs_stack功能解密

    openGauss3.1.0 版本的 gs_stack 功能解密 不管是测试还是研发,工作中总有遇到各种各样的问题.比如,你有没有遇到过在数据库中执行某个 SQL,却一直不返回结果,这时候的你是不是非 ...

  8. Linux之sudo

    [摘要] 生产环境中为了系统的安全性,Linux主机的root权限是只能管理器使用,普通用户不具有root权限,但是可以通过sudo获取root权限执行一些操作. 一.知识要点 wheel组 在Lin ...

  9. 重新整理数据结构与算法(c#)——算法套佛洛伊德算法[三十二]

    前言 佛洛伊德算法和迪杰斯特拉算法非常像,但是它求的是任何一个点到其他点之间的距离. 假设有一张图: 转换为矩阵为: 他们的前驱为: 可能上面表述前驱不清楚,举个例子. 看下图: 这第二种图表示,从A ...

  10. 从零开始写 Docker(十一)---实现 mydocker exec 进入容器内部

    本文为从零开始写 Docker 系列第十一篇,实现类似 docker exec 的功能,使得我们能够进入到指定容器内部. 完整代码见:https://github.com/lixd/mydocker ...