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