vluogu P4117 [Ynoi2018] 五彩斑斓的世界

本文介绍了一种高效的离线查询更新结构算法,通过并查集和区间维护技术实现快速的数据更新与查询操作。该算法适用于批量数据处理场景,如大规模数据集上的统计分析和查询优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<bits/stdc++.h>
#define N 1000050
#define RE register
using namespace std;

int fa[N], rt[N], size[N], val[N], a[N], n, m, blo, bel[N], mx, tg, ans[N >> 1];
inline int get(int x) { return fa[x] == x? x : fa[x] = get(fa[x]); }
inline void merge(int x, int y) {
    if(!rt[y]) {
        rt[y] = rt[x];
        val[rt[y]] = y;
    } else fa[rt[x]] = rt[y];
    size[y] += size[x]; rt[x] = size[x] = 0;
}
inline void build(int l, int r) {
    memset(rt, 0, sizeof rt);
    memset(size, 0, sizeof size);
    mx = tg = 0;
    for(RE int i = l; i <= r; i ++) { mx = max(mx, a[i]);
        if(rt[a[i]]) fa[i] = rt[a[i]];
        else {
            fa[i] = rt[a[i]] = i;
            val[i] = a[i];
        }
        size[a[i]] ++;
    }
}
inline void change(int l, int r, int x) {
    if(x * 2 <= mx - tg) {
        for(RE int j = tg + 1; j <= tg + x; j ++)
            if(rt[j]) merge(j, j + x);
        tg += x;
    } else {
        for(RE int j = mx; j > x + tg; j --)
            if(rt[j]) merge(j, j - x);
        if(x < mx - tg) mx = tg + x;
    }
}
inline void calc(int l, int r, int L, int R, int x, int id) {
    if(x + tg > 100001) return ;
//     if(id == 2) {
//            printf("  %d %d    %d\n", l, r, x + tg);
//            for(int i = 1; i <= n; i ++) printf("%d ", val[get(i)]); printf("\n");
//        }
    if(L <= l && r <= R) ans[id] += size[x + tg];
    else {
        for(RE int i = max(l, L); i <= min(r, R); i ++)
            if(val[get(i)] == x + tg) ans[id] ++;
    }
}
inline void rebuild(int l, int r, int L, int R, int x) {
    for(RE int i = l; i <= r; i ++) a[i] = val[get(i)], size[a[i]] = rt[a[i]] = 0, a[i] -= tg;
    for(RE int i = l; i <= r; i ++) val[i] = 0;
    for(RE int i = max(l, L); i <= min(r, R); i ++)
        if(a[i] > x) a[i] -= x;
    
    mx = tg = 0;
    for(RE int i = l; i <= r; i ++) { mx = max(mx, a[i]);
        if(rt[a[i]]) fa[i] = rt[a[i]];
        else {
            fa[i] = rt[a[i]] = i;
            val[i] = a[i];
        }
        size[a[i]] ++;
    }
}
struct Q {
    int o, l, r, x, id;
} q[N >> 1];
inline int read() {
    register int x = 0;
    register char ch = getchar();
    for(; ch < '0' || ch > '9'; ) ch = getchar();
    for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x << 1) + (ch - 48), ch = getchar();
    return x;
}
inline void write(register int x) {
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    n = read(), m = read();
    for(RE int i = 1; i <= n; i ++) a[i] = read();
    blo = 1200;
  // blo = min(n, 2 * m / (int)sqrt(n) + 1);
    for(RE int i = 1; i <= n; i ++) bel[i] = (i - 1) / blo + 1;
  //  printf("** %d\n", blo);
    int tot = 0;
    for(RE int i = 1; i <= m; i ++) q[i].o = read(), q[i].l = read(), q[i].r = read(), q[i].x = read(), q[i].id = q[i].o == 2? ++ tot : 0;
    
    for(RE int i = 1; i <= bel[n]; i ++) {
        int l = (i - 1) * blo + 1, r = min(n, i * blo);
        build(l, r);
        for(RE int j = 1; j <= m; j ++) {
            int L = q[j].l, R = q[j].r, x = q[j].x, o = q[j].o, id = q[j].id;
            if(R < l || L > r) continue;
            if(o == 1) {
                if(L <= l && r <= R) change(l, r, x);
                else rebuild(l, r, L, R, x);
             //   printf("   %d %d %d %d %d        %d\n", l, r, L, R, x, ans[2]);
            } else calc(l, r, L, R, x, id);
        }
    }
    for(RE int i = 1; i <= tot; i ++) write(ans[i]), puts("");
    return 0;
}
/*
10 5
3 4 6 6 4 4 9 9 7 6
2 5 9 3
1 1 3 3
1 6 10 2
1 10 10 8
2 4 10 6
  */

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值