C. Fixed Point Removal

目录

1.Problem

2.Input

3.Output

4.Examples

4.1input

4.2output

5.Code

6.Conclusion


1.Problem

Let a1,…,ana1,…,an be an array of nn positive integers. In one operation, you can choose an index ii such that ai=iai=i, and remove aiai from the array (after the removal, the remaining parts are concatenated).

The weight of aa is defined as the maximum number of elements you can remove.

You must answer qq independent queries (x,y)(x,y): after replacing the xx first elements of aa and the yy last elements of aa by n+1n+1 (making them impossible to remove), what would be the weight of aa?

2.Input

The first line contains two integers nn and qq (1≤n,q≤3⋅1051≤n,q≤3⋅105)  — the length of the array and the number of queries.

The second line contains nn integers a1a1, a2a2, ..., anan (1≤ai≤n1≤ai≤n) — elements of the array.

The ii-th of the next qq lines contains two integers xx and yy (x,y≥0x,y≥0 and x+y<nx+y<n).

3.Output

Print qq lines, ii-th line should contain a single integer  — the answer to the ii-th query.

4.Examples

4.1input

13 5
2 2 3 9 5 4 6 5 7 8 3 11 13
3 1
0 0
2 4
5 0
0 12

4.2output

5
11
6
1
0

5.Code

#include <bits/stdc++.h>

#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

template <typename T> bool chkmax(T &x, T y) { return x < y ? x = y, true : false; }
template <typename T> bool chkmin(T &x, T y) { return x > y ? x = y, true : false; }

int readint() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

const int MAXN = 300005;
const int MAXQ = 1100000;
const int MAXPST = 10000005;

int n, q;
int a[MAXN], lf[MAXN];

namespace sgt {
int lazy[MAXQ], maxa[MAXQ];

void pushdown(int id) {
    if (lazy[id]) {
        lazy[id << 1] += lazy[id], maxa[id << 1] += lazy[id];
        lazy[id << 1 | 1] += lazy[id], maxa[id << 1 | 1] += lazy[id];
        lazy[id] = 0;
    }
}

int find(int id, int l, int r, int ql, int qr, int c) {
    if (maxa[id] < c) return l - 1;
    if (l == r) return maxa[id] >= c ? l : l - 1;
    pushdown(id);
    int mid = (l + r) / 2;
    if (qr <= mid) return find(id << 1, l, mid, ql, qr, c);
    else if (ql > mid) return find(id << 1 | 1, mid + 1, r, ql, qr, c);
    else if (maxa[id << 1 | 1] >= c) return find(id << 1 | 1, mid + 1, r, mid + 1, qr, c);
    else return find(id << 1, l, mid, ql, mid, c);
}

void change(int id, int l, int r, int ql, int qr, int c) {
    if (ql > qr) return;
    if (l == ql && r == qr) return (void)(lazy[id] += c, maxa[id] += c);
    pushdown(id);
    int mid = (l + r) / 2;
    if (qr <= mid) change(id << 1, l, mid, ql, qr, c);
    else if (ql > mid) change(id << 1 | 1, mid + 1, r, ql, qr, c);
    else change(id << 1, l, mid, ql, mid, c), change(id << 1 | 1, mid + 1, r, mid + 1, qr, c);
    maxa[id] = max(maxa[id << 1], maxa[id << 1 | 1]);
}
}

namespace pst {
int ncnt;
int vs[MAXN], lch[MAXPST], rch[MAXPST], val[MAXPST];

void build(int id, int l, int r) {
    if (l == r) return;
    int mid = (l + r) / 2;
    build(lch[id] = ++ncnt, l, mid);
    build(rch[id] = ++ncnt, mid + 1, r);
}

int change(int id, int l, int r, int x) {
    int rt = ++ncnt;
    val[rt] = val[id] + 1, lch[rt] = lch[id], rch[rt] = rch[id];
    if (l == r) return rt;
    int mid = (l + r) / 2;
    if (x <= mid) lch[rt] = change(lch[rt], l, mid, x);
    else rch[rt] = change(rch[rt], mid + 1, r, x);
    return rt;
}

int query(int id1, int id2, int l, int r, int ql, int qr) {
    if (l == ql && r == qr) return val[id2] - val[id1];
    int mid = (l + r) / 2;
    if (qr <= mid) return query(lch[id1], lch[id2], l, mid, ql, qr);
    else if (ql > mid) return query(rch[id1], rch[id2], mid + 1, r, ql, qr);
    else return query(lch[id1], lch[id2], l, mid, ql, mid) + query(rch[id1], rch[id2], mid + 1, r, mid + 1, qr);
}
}

int main() {
    n = readint(); q = readint();
    for (int i = 1; i <= n; i++) a[i] = readint() - i;
    for (int i = 1; i <= n; i++) {
        if (a[i] > 0) lf[i] = 0;
        else {
            int pl = sgt::find(1, 1, n, 1, i, -a[i]);
            lf[i] = pl;
            sgt::change(1, 1, n, 1, pl, 1);
        }
    }
    pst::build(pst::vs[0] = 1, 0, n);
    for (int i = 1; i <= n; i++) pst::vs[i] = pst::change(pst::vs[i - 1], 0, n, lf[i]);
    int x, y, l, r;
    while (q--) {
        x = readint(); y = readint();
        l = x + 1, r = n - y;
        printf("%d\n", pst::query(pst::vs[l - 1], pst::vs[r], 0, n, l, r));
    }
    return 0;
}

6.Conclusion

这段代码是一个C++程序,主要实现了一个复杂的数据结构,涉及到线段树(Segment Tree)和持久化线段树(Persistent Segment Tree)的概念。以下是代码的简要说明:

  1. 头文件和宏定义:包含了一些标准的C++头文件,以及一些宏定义,用于简化代码中的一些操作,如pb(push_back)、mp(make_pair)等。

  2. 命名空间和类型定义:使用了std命名空间,并定义了一些类型别名,如ll(long long)、ull(unsigned long long)、pii(pair of integers)和pll(pair of long long)等。

  3. 读取整数的函数readint函数用于从标准输入中读取一个整数,通过字符处理实现。

  4. 全局变量和常量:定义了一些全局变量和常量,如数组alf,以及常量MAXNMAXQMAXPST

  5. 命名空间sgt:实现了线段树的一些操作,包括pushdown(向下传递懒惰标记)、find(查找满足条件的位置)和change(更新区间的值)等。

  6. 命名空间pst:实现了持久化线段树的一些操作,包括build(建树)、change(更新节点的值)和query(查询区间的值)等。

  7. 主函数:程序的入口,首先读取输入的n和q,然后通过readint函数读取数组a。接着,使用线段树处理a数组,找到满足条件的位置并更新线段树。之后,建立持久化线段树。最后,通过读取查询,使用持久化线段树查询指定区间的值并输出。

需要注意的是,这段代码实现了一种特定的算法或数据结构,如果要理解代码的具体逻辑和功能,需要深入了解线段树和持久化线段树的原理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向阳而生__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值