数对(动态开点)

简介: 笔记

题目描述


给定一个长度为 n nn 的整数数列 和两个整数 x xx、y yy。

10.png

请你判断一共有多少个数对 ( l , r ) (l, r)(l,r) 同时满足以下条件:



输入描述


11.png

输出描述


输出一个整数,表示满足条件的数对的数量。


示例1#


输入:


5 3 3

4 6 5 3 7


输出:


5


说明:


满足要求的数对一共 5组,分别是 (1,1)、(2,2)、(3,3)、(4,4)、(3,4)


分析


12.png

代码

注意 i ii从1开始,那么s [ l − 1 ] s[l - 1]s[l−1]中即从0 00开始,所以事先需要插入 s [ 0 ] s[0]s[0]这个节点。


然后就是套动态开点线段树的模板了。


#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int N = 500010;
struct node {
    int l, r;
    int v, add;
}tr[N << 6];
int n, x, y;
int a[N], ans, s[N];
int root, idx;
int L = -(1ll << 60), R = (1ll << 60);
void pushdown(int p, int l, int r) {
    if(tr[p].add) {
        int mid = l + r >> 1;
        tr[tr[p].l].add += tr[p].add, tr[tr[p].l].v += (mid - l + 1) * tr[p].add;
        tr[tr[p].r].add += tr[p].add, tr[tr[p].r].v += (r - mid) * tr[p].add;
        tr[p].add = 0;
    }
}
void pushup(int p) {
    tr[p].v = tr[tr[p].l].v + tr[tr[p].r].v;
}
void modify(int &p, int l, int r, int ql, int qr, int v) {
    if(!p) p = ++idx;
    if(l >= ql && r <= qr) { tr[p].add += v; tr[p].v += (r - l + 1) * v; return ; }
    pushdown(p, l, r);
    int mid = l + r >> 1;
    if(ql <= mid) modify(tr[p].l, l, mid, ql, qr, v);
    if(qr > mid) modify(tr[p].r, mid + 1, r, ql, qr, v);
    pushup(p);
    return ;
}
int query(int p, int l, int r, int ql, int qr) {
  if(!p) return 0;
    if(l >= ql && r <= qr) return tr[p].v;
    int mid = l + r >> 1;
    pushdown(p, l, r);
    int res = 0;
    if(ql <= mid) res += query(tr[p].l, l, mid, ql, qr);
    if(qr > mid) res += query(tr[p].r, mid + 1, r, ql, qr);
    return res;
}
signed main() {
    cin >> n >> x >> y;
    for (int i = 1; i <= n; i++) { cin >> a[i]; a[i] -= y; s[i] = s[i - 1] + a[i]; }
    modify(root, L, R, s[0], s[0], 1);
    for (int i = 1; i <= n; i++) {
        ans += query(root, L, R, s[i] - x, R);
        modify(root, L, R, s[i], s[i], 1);
    }
    cout << ans << endl;
  return 0;
}
相关文章
|
5月前
指针\分配动态空间-筛选法求质数
指针\分配动态空间-筛选法求质数
33 5
|
6月前
|
算法 测试技术 C#
【线段树 区间位运算模板】3117划分数组得到最小的值之和
【线段树 区间位运算模板】3117划分数组得到最小的值之和
|
6月前
|
算法 Java C++
动态求连续区间和
动态求连续区间和
42 0
|
11月前
|
算法 测试技术 C#
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
|
11月前
|
算法 测试技术 C#
C++前缀和算法的应用:使数组相等的最小开销
C++前缀和算法的应用:使数组相等的最小开销
|
算法 测试技术 C++
C++算法:让数组不相等的最小总代价
C++算法:让数组不相等的最小总代价
|
算法 前端开发 程序员
调整数组元素顺序
调整数组元素顺序
调整数组元素顺序
一道题,最小操作次数使数组元素相等引发的思考
给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。
115 0
一道题,最小操作次数使数组元素相等引发的思考
|
机器学习/深度学习 人工智能 算法
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)
280 0
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)