说句闲话,研究第二分块的最好方法是
查看原帖
说句闲话,研究第二分块的最好方法是
66511
DPair楼主2020/12/13 18:30

帮我卡常,祝你们成功。

好吧我自己也不知道我为什么卡不过去,感觉算法是对的。

是我人傻常数大吗。。。

#include <cstdio>
template <typename T>
inline T mn(T x, T y) {return x < y ? x : y;}
template <typename T>
inline T mx(T x, T y) {return x > y ? x : y;}
template <typename T>
inline void chmin(T &x, T y) {(x > y) && (x = y);}
template <typename T>
inline void chmax(T &x, T y) {(x < y) && (x = y);}
template <typename T>
inline void read(T &x){
    x = 0;int fu = 1;
    char c = getchar();
    while(c > 57 || c < 48){
        if(c == 45) fu = -1;
        c = getchar();
    }
    while(c <= 57 && c >= 48){
        x = (x << 3) + (x << 1) + c - 48;
        c = getchar();
    }
    x *= fu;
}
template <typename T>
inline void fprint(T x){
    if(x < 0) putchar(45), x = -x;
    if(x > 9) fprint(x / 10);
    putchar(x % 10 + 48);
}
template <typename T>
inline void fprint(T x, char ch){
    fprint(x);putchar(ch);
}
#define MAXN 1000005
#define MAXM 500005
#define V 100007
#define block 888
const int B = MAXN / block + 5;
int n, m, a[MAXN];
int ans[MAXM], bel[MAXN];
int fa[MAXN], sz[MAXN], rt[V], val[MAXN];
int fst[B], lst[B];
int opt[MAXM], l[MAXM], r[MAXM], x[MAXM];
int tag, R;
int find(int x){
    if(fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}
inline void merge(int x, int y){
    if(rt[y]) fa[rt[x]] = rt[y];
    else rt[y] = rt[x], val[rt[y]] = y;
    sz[y] += sz[x];
    sz[x] = rt[x] = 0;
}
inline void rebuild(int x){
    for (register int i = fst[x];i <= lst[x];i ++) a[i] = val[find(i)], sz[a[i]] = rt[a[i]] = 0, a[i] -= tag;
    for (register int i = fst[x];i <= lst[x];i ++) fa[i] = 0;
}
int tot = -0x3f3f3f3f;
inline void build(int x){
    tag = 0;R = -0x3f3f3f3f;
    for (register int i = fst[x];i <= lst[x];i ++) {
        chmax(R, a[i]);
        if(!rt[a[i]]) rt[a[i]] = i, val[i] = a[i];
        fa[i] = rt[a[i]];
        sz[a[i]] ++;
    }
}
int main(){
    read(n);read(m);
    tot = -0x3f3f3f3f;
    for (register int i = 1;i <= n;i ++){
        read(a[i]);bel[i] = (i - 1) / block + 1;
        if(!fst[bel[i]]) fst[bel[i]] = i;
        lst[bel[i]] = i;
        chmax(tot, a[i]);
    }
    for (register int i = 1;i <= m;i ++) read(opt[i]), read(l[i]), read(r[i]), read(x[i]);
    for (register int i = 1;i <= bel[n];i ++){
        build(i);
        for (register int j = 1;j <= m;j ++){
            if(opt[j] == 1){
                if(bel[l[j]] == bel[r[j]]){
                    if(bel[l[j]] ^ i) continue;
                    rebuild(i);
                    for (register int k = l[j];k <= r[j];k ++)
                        if(a[k] > x[j]) a[k] -= x[j];
                    build(i);
                }
                else{
                    if(i > bel[l[j]] && i < bel[r[j]]){
                        if((x[j] << 1) <= R - tag){
                            for (register int k = tag + x[j];k > tag;k --)
                                if(rt[k]) merge(k, k + x[j]);
                            tag += x[j];
                        }
                        else{
                            for (register int k = R;k > x[j] + tag;k --)
                                if(rt[k]) merge(k, k - x[j]);
                            R = mn(R, tag + x[j]);
                        }
                    }
                    else{
                        if(i == bel[l[j]]){
                            rebuild(i);
                            for (register int k = l[j];k <= lst[bel[l[j]]];k ++)
                                if(a[k] > x[j]) a[k] -= x[j];
                            build(i);
                        }
                        else if(i == bel[r[j]]){
                            rebuild(i);
                            for (register int k = fst[bel[r[j]]];k <= r[j];k ++)
                                if(a[k] > x[j]) a[k] -= x[j];
                            build(i);
                        }
                    }
                }
            }
            else{
                if(bel[l[j]] == bel[r[j]]){
                    if(bel[l[j]] ^ i) continue;
                    for (register int k = l[j];k <= r[j];k ++)
                        if(val[find(k)] - tag == x[j]) ans[j] ++;
                }
                else{
                    if(x[j] + tag > tot) continue;
                    if(i > bel[l[j]] && i < bel[r[j]]) ans[j] += sz[x[j] + tag];
                    else{
                        if(i == bel[l[j]]){
                            for (register int k = l[j];k <= lst[bel[l[j]]];k ++)
                                if(val[find(k)] - tag == x[j]) ans[j] ++;
                        }
                        else if(i == bel[r[j]]){
                            for (register int k = fst[bel[r[j]]];k <= r[j];k ++)
                                if(val[find(k)] - tag == x[j]) ans[j] ++;
                        }
                    }
                }
            }
        }
        rebuild(i);
    }
    for (register int j = 1;j <= m;j ++)
        if(opt[j] == 2) fprint(ans[j], 10);
}
2020/12/13 18:30
加载中...