序列 [线段树]

序列

在这里插入图片描述


color{red}{正解部分}

使用 线段树 维护 bb, 初值为 bi-b_i, 每次修改时, 若一个位置上的值变为了 00, 则说明其会对答案产生新的贡献,
在外部使用 树状数组 将贡献计入答案, 然后将该位置的值 重置为 bi-b_i, 重置的时间复杂度是 O(logN)O(log N) .

考虑最坏情况, 每次操作 [1,N][1, N],
这样 bi=1b_i=1 的位置最多重置 NNbi=2b_i=2 最多重置 N2frac{N}{2} 次, bi=3b_i=3 最多 …

所以总共需要 重置 O(NlogN)O(N log N) 次, 总时间复杂度 O(Nlog2N)O(N log^2 N) .


color{red}{实现部分}

重置 可以在 修改 时 使用 update()update() 实现 .

#include<bits/stdc++.h>
#define reg register
#define fi first
#define se second
typedef std::pair<int, int> pr;

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 100005;
const int inf = 0x3f3f3f3f;

int N;
int M;
int Tmp_1;
int B[maxn];

struct Bit_Tree{
        int v[maxn], lim;
        void Add(int k, int x){ while(k<=lim)v[k]+=x,k+=k&-k; }
        int Query(int k){ if(k<=0)return 0; int s=0; while(k)s+=v[k],k-=k&-k; return s; }
} bit_t;

struct Segment_Tree{

        struct Node{ int l, r, t, max_v, id; } T[maxn << 2];

        void Push_down(const int &k){ 
                T[k].max_v += T[k].t;
                if(T[k].l == T[k].r) return T[k].t = 0, void();
                T[k<<1].t += T[k].t, T[k<<1|1].t += T[k].t, T[k].t = 0;
        }

        void Push_up(const int &k){
                if(T[k<<1].t) Push_down(k<<1);
                if(T[k<<1|1].t) Push_down(k<<1|1);
                T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v); 
                if(T[k<<1].max_v == T[k].max_v) T[k].id = k<<1;
                else T[k].id = k<<1|1;
        }

        void Build(int k, int l, int r){
                T[k].l = l, T[k].r = r; if(l == r) return T[k].max_v = B[l], T[k].id = k, void();
                int mid = l+r >> 1; Build(k<<1, l, mid), Build(k<<1|1, mid+1, r); Push_up(k);
        }

        void update(int k){
                int l = T[k].l, r = T[k].r;
                if(T[k].t) Push_down(k);
                if(l == r) return bit_t.Add(l, 1), T[k].max_v=B[l], void();
                update(T[k].id); Push_up(k);
        }

        void Modify(int k, const int &ql, const int &qr, const int &aim){
                int l = T[k].l, r = T[k].r;
                if(T[k].t) Push_down(k);
                if(r < ql || l > qr) return ;
                if(ql <= l && r <= qr){
                        T[k].t += aim, Push_down(k); 
                        while(!T[k].max_v) update(k);
                        return ;
                }
                Modify(k<<1, ql, qr, aim), Modify(k<<1|1, ql, qr, aim); Push_up(k);
        }

        int Query(int k, const int &ql, const int &qr){
                int l = T[k].l, r = T[k].r;
                if(T[k].t) Push_down(k);
                if(r < ql || l > qr) return -inf;
                if(ql <= l && r <= qr) return T[k].max_v;
                return std::max(Query(k<<1, ql, qr), Query(k<<1|1, ql, qr));
        }

} seg_t;

int main(){
        N = read(), M = read();
        for(reg int i = 1; i <= N; i ++) B[i] = -read();
        seg_t.Build(1, 1, N); bit_t.lim = N;
        for(reg int i = 1; i <= M; i ++){
                int opt = read(), l = read(), r = read();
                if(opt == 2) printf("%d
", bit_t.Query(r) - bit_t.Query(l-1));
                else seg_t.Modify(1, l, r, 1);
        }
        return 0;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822420.html