可持久化线段树改版(求l-r区间内<=x的数的总和)

#include<bits/stdc++.h>

using namespace std;
const int N = 1e6 + 10;

struct CMT {
    int seq[N << 1], rt[N], tot, m;
    struct {
        int l, r;
        long long sum;
    } t[N << 5];

    inline void init(int *a, int n) {
        memcpy(seq + 1, a + 1, sizeof(int) * n);
        for (int i = 1; i <= n; i++)seq[n + i] = seq[i] + 1;
        sort(seq + 1, seq + 2 * n + 1);
        m = unique(seq + 1, seq + 2 * n + 1) - seq - 1;
        for (int i = 1; i <= n; ++i)
            rt[i] = update(rt[i - 1], 1, m, lower_bound(seq + 1, seq + 1 + m, a[i]) - seq);
    }

    int update(int p, int l, int r, int x) {
        int dir = ++tot;
        t[dir] = t[p], t[dir].sum += seq[x];
        if (l == r)return dir;
        int mid = (l + r) >> 1;
        x <= mid ? (t[dir].l = update(t[dir].l, l, mid, x)) : (t[dir].r = update(t[dir].r, mid + 1, r, x));
        return dir;
    }

    long long ask(int u, int v, int l, int r, int x) {
        if (r <= x)return t[v].sum - t[u].sum;
        int mid = (l + r) >> 1;
        return ask(t[u].l, t[v].l, l, mid, x) + (x > mid ? ask(t[u].r, t[v].r, mid + 1, r, x) : 0);
    }

    inline long long solve(int l, int r, long long x) {
        x = upper_bound(seq + 1, seq + 1 + m, x) - seq - 1;
        return x ? ask(rt[l - 1], rt[r], 1, m, x) : 0;
    }
} C;

int n, q, a[N];
long long ans;

int main() {
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
    C.init(a, n);
    while (q--) {
        int l, r;
        scanf("%d%d", &l, &r);
        l = (l + ans) % n + 1, r = (r + ans) % n + 1;
        if (l > r)swap(l, r);
        ans = 0;
        while (true) {
            long long d = C.solve(l, r, ans + 1) - ans;
            if (!d)break;
            ans += d;
        }
        printf("%lld\n", ++ans);
    }
    return 0;
}

 

posted @ 2021-04-13 21:42  _LH2000  阅读(57)  评论(0编辑  收藏  举报