洛谷-P2801 教主的魔法 分块
生活随笔
收集整理的這篇文章主要介紹了
洛谷-P2801 教主的魔法 分块
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目
題目鏈接
題意
- 修改:將一個區間內所有的數+C。
- 查詢:查詢一個區間內>C的數字有多少個。
題解
很經典的分快算法題目。
將數列分塊以后,對塊內的元素進行排序。
- 當我們要做修改操作的時候:遇到要修改的完整的塊的時候,我們給它在addmark數組的相應的位置+C,標記為我對整個區間做了一個修改操作,有點類似于帶lazy標記的線段樹的操作。當要修改的部分區間不是完整的塊的時候,我們檢查這部分區間所在的塊的addmark有沒有被標記,如果有就對這個塊整個進行更新操作,然后把addmark清零,并且暴力把這部分區間的元素+C。時間復雜度為O(n ̄√+n ̄√?logn ̄√))O(n+n?logn))。
- 當我們遇到查詢操作的時候:當我們要查詢的部分區間不屬于完整的塊的時候,如果塊的addmark被標記過了,那么更新這個塊,然后再暴力查詢這個“部分區間”。當我們要查詢的區間屬于完整的塊的時候,由于這個區間是有序的,我們只需要使用二分搜索結合addmark,就可以確定出該塊內>C的元素有多少個。時間復雜度O(n ̄√+n ̄√?logn ̄√))O(n+n?logn))。
因此總的時間復雜度就是:O((n ̄√+n ̄√?logn ̄√)?m)O((n+n?logn)?m)
代碼
#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; }總結
以上是生活随笔為你收集整理的洛谷-P2801 教主的魔法 分块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 勃勃生机的意思 勃勃生机简述
- 下一篇: 风景名胜的胜的意思 风景名胜的胜的意思是