Luogu-P2801 The leader's magic block

topic

topic link

meaning of the title

  • Modification: Add all numbers in an interval + C.
  • Query: Query how many numbers > C in an interval.

answer

It's a very classic topic of fast-paced algorithm.
After dividing the sequence into blocks, sort the elements within the blocks.

  • When we want to modify the operation: when we encounter the complete block to be modified, we give it +C in the corresponding position of the addmark array, marking that I have done a modification operation on the entire interval, which is somewhat similar to that with lazy Operations on the marked segment tree. When the part of the range to be modified is not a complete block, we check whether the addmark of the block where this part of the range is located is marked, if so, update the entire block, then clear the addmark, and violently remove this part Element of the interval + C. The time complexity is O ( n + n l O g n ) )
  • When we encounter a query operation: when the part of the range we want to query does not belong to a complete block, if the addmark of the block has been marked, then update the block, and then violently query the "partial range". When the interval we want to query belongs to a complete block, since the interval is ordered, we only need to use binary search combined with addmark to determine how many elements > C in the block. time complexity O ( n + n l O g n ) )

So the total time complexity is: O ( ( n + n l O g n ) m )

code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
#define pr(x) cout<<#x<<":"<<x<<endl
int Base = 1000;
ll a[1000007],addmark[1007],C;
int n,q,L,R;
char op;
vector<ll> vec[1007];

inline void read(ll &x){
    scanf("%lld",&x);
}

inline void read(int &x){
    scanf("%d",&x);
}

inline void read(char &c){
    scanf(" %c",&c);
}

void work(int bl){
    if(addmark[bl]){

        for(int t = bl*Base;t < (bl+1)*Base && t < n;++t){
            a[t] += addmark[bl];
        }
        for(auto &i : vec[bl]){
            i += addmark[bl];
        }

        addmark[bl] = 0;
    }
}

void buildvec(int bl){
    vec[bl].clear();
    for(int t = bl*Base;t < (bl+1)*Base && t < n;++t){
        vec[bl].push_back(a[t]);
    }
    sort(vec[bl].begin(),vec[bl].end());
}

int main(){
    scanf("%d%d",&n,&q);
    for(int i = 0;i < n;++i){
        int bl = i/Base;
        read(a[i]);
        vec[bl].push_back(a[i]);
        if((i+1)%Base == 0 || i == n-1){
            sort(vec[bl].begin(),vec[bl].end());
        }
    }


    for(int i = 0;i < q;++i){
        read(op);read(L);read(R);read(C);
        L--;R--;
        ll rep = 0;
        if(op == 'A'){
            if(L % Base != 0 && addmark[L/Base]) {
                work(L / Base);
            }

            if((R+1)%Base != 0 && addmark[R/Base]){
                work(R / Base);
            }

            int ans = 0;
            for(;L <= R && L % Base != 0;L++){
                ans += a[L] >= C;
            }

            for(;L <= R && (R+1)%Base != 0;R--){
                ans += a[R] >= C;
            }

            if(L > R){
                printf("%d\n",ans);
                continue;
            }
            int bl = L / Base;
            int br = R / Base;
            for(;bl <= br;++bl){
                auto loc = lower_bound(vec[bl].begin(),vec[bl].end(),C-addmark[bl]);
                int ad = vec[bl].size() - (loc - vec[bl].begin());
                ans += max(0,ad);
            }
            printf("%d\n",ans);

        }
        else{
            int bl,br;

            if(L % Base != 0){
                work(L / Base);
                bl = L / Base;
                for(;L <= R && L % Base != 0;++L){
                    a[L] += C;
                    //pr(L);
                    //pr(a[L]);
                }

                buildvec(bl);
            }

            if((R+1) % Base != 0){
                work(R / Base);
                br = R / Base;
                for(;L <= R && (R+1) % Base != 0;--R)
                    a[R] += C;

                buildvec(br);
            }



            if(L < R){
                bl = L / Base;
                br = R / Base;
                for(;bl <= br;++bl){
                    addmark[bl] += C;
                }
            }
        }
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325762376&siteId=291194637