51nod1394 差和问题 值域线段树

水题.....

插入一个值$v$时,对于$[0, v - 1]$和$[v + 1, inf]$的点分别考虑就行了

删除相当于减去插入的贡献

用动态开点线段树卡点常数就过去了

复杂度$O(n \log n)$

#include <cstdio>
#include <cstring>
using namespace std;

extern inline char gc() {
    static char RR[23456], *S = RR + 23333, *T = RR + 23333;
    if(S == T) fread(RR, 1, 23333, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0'&& c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

int wr[50], rw;
#define pc(o) *O ++ = o
char WR[30000005], *O = WR;
template <typename re>
inline void write(re x) {
    if(!x) pc('0');
    if(x < 0) x = -x, pc('-');
    while(x) wr[++ rw] = x % 10, x /= 10;
    while(rw) pc(wr[rw --] + '0'); pc('\n');
}

#define ll long long
#define ri register int
#define sid 5000050

ll ans;
ll sum[sid];
int n, q, id, rt;
int sz[sid], ls[sid], rs[sid];
const int inf = 1e9 + 5;

inline void upd(int o) {
    sz[o] = sz[ls[o]] + sz[rs[o]];
    sum[o] = sum[ls[o]] + sum[rs[o]];
}

inline void ins(int &o, int l, int r, int p, int v) {
    if(!o) o = ++ id;
    if(l == r) { sz[o] += v; sum[o] = 1ll * sz[o] * p; return; }
    int mid = (l + r) >> 1;
    if(p <= mid) ins(ls[o], l, mid, p, v);
    else ins(rs[o], mid + 1, r, p, v);
    upd(o);
}

inline ll qry(int o, int l, int r, int ml, int mr) {
    if(!o || ml > r || mr < l) return 0;
    if(ml <= l && mr >= r) return sum[o];
    int mid = (l + r) >> 1;
    return qry(ls[o], l, mid, ml, mr) + qry(rs[o], mid + 1, r, ml, mr);
}

inline int qsz(int o, int l, int r, int ml, int mr) {
    if(!o || ml > r || mr < l) return 0;
    if(ml <= l && mr >= r) return sz[o];
    int mid = (l + r) >> 1;
    return qsz(ls[o], l, mid, ml, mr) + qsz(rs[o], mid + 1, r, ml, mr);   
}

inline void ins(int v, int opt) {
    if(opt == -1 && qsz(rt, 0, inf, v, v) == 0) { write(-1); return; }
    ins(rt, 0, inf, v, opt);
    ans += opt * (-qry(rt, 0, inf, 0, v - 1) + 1ll * qsz(rt, 0, inf, 0, v - 1) * v);
    ans += opt * (qry(rt, 0, inf, v + 1, inf) - 1ll * qsz(rt, 0, inf, v + 1, inf) * v);
}

int main() {
    n = read(); q = read();
    for(ri i = 1; i <= n; i ++) ins(read(), 1);
    for(ri i = 1; i <= q; i ++) {
        int opt = read();
        if(opt == 1) ins(read(), 1);
        else if(opt == 2) ins(read(), -1);
        else write(ans);
    }
    fwrite(WR, 1, O - WR, stdout);
    return 0;
}

 

posted @ 2018-08-29 16:49  remoon  阅读(177)  评论(0编辑  收藏  举报