CDQ 分治算法模板
生活随笔
收集整理的這篇文章主要介紹了
CDQ 分治算法模板
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
CDQ分治
1.三維偏序問(wèn)題:三維偏序(陌上花開(kāi))
#include<bits/stdc++.h> #define RG register #define IL inline #define _ 200005 using namespace std; IL int gi(){RG int data = 0 , m = 1; RG char ch = 0;while(ch != '-' && (ch<'0'||ch>'9'))ch = getchar();if(ch == '-'){m = -1; ch = getchar();}while('0'<=ch && ch<='9')data = (data<<3) + (data<<1) + (ch - '0') , ch = getchar();return (m) ? data : -data; }int tot,bt[_],n,k,f[_],g[_],blg[_]; long long ans[_];struct Node{int a, b, c , w , id;//w記錄這個(gè)節(jié)點(diǎn)對(duì)應(yīng)多少個(gè)真實(shí)節(jié)點(diǎn),id則是其對(duì)應(yīng)編號(hào).bool operator <(const Node &B)const{return (b == B.b) ? c <= B.c : b < B.b;} }; Node q1[_],q[_],tmp[_];namespace BIT{IL void Update(RG int ps,RG int dt){for(RG int i = ps; i <= k; i += (i&-i))bt[i] += dt;}IL void Clear(RG int ps){for(RG int i = ps; i <= k; i += (i&-i))bt[i] = 0;}IL int Query(RG int ps){RG int res = 0;for(RG int i = ps; i > 0; i -= (i&-i))res += bt[i];return res;} }void cdq(RG int L,RG int R){if(L == R)return;RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);RG int l = L , r = mid+1 , oo = L-1;while(l <= mid && r <= R){if(q[l] < q[r])BIT::Update(q[l].c,q[l].w) ,tmp[++oo] = q[l++];elseg[q[r].id] += BIT::Query(q[r].c) ,tmp[++oo] = q[r++];}while(l <= mid)tmp[++oo] = q[l++];while(r <= R)g[q[r].id] += BIT::Query(q[r].c) ,tmp[++oo] = q[r++];for(RG int i = L; i <= R; i ++)BIT::Clear(tmp[i].c) , q[i] = tmp[i];return; }IL bool cmp(Node a,Node b){if(a.a != b.a)return a.a < b.a;if(a.b != b.b)return a.b < b.b;if(a.c != b.c)return a.c < b.c;return a.id < b.id; //注意:這里一定要隨便定義一個(gè)優(yōu)先級(jí) } IL bool Equl(int nw,int cp){if(!cp)return false;else return (q1[nw].a==q[cp].a &&q1[nw].b==q[cp].b && q1[nw].c==q[cp].c); }int main(){n = gi(); k = gi();for(RG int i = 1,a,b,c; i <= n; i ++)a = gi(),b = gi(),c = gi(),q1[i] = (Node){a , b , c , 1 , i};//去重:tot = 0;sort(q1+1,q1+n+1,cmp);for(RG int i = 1; i <= n; i ++){if(!Equl(i,tot))q[++tot] = q1[i] , q[tot].w = 1 , q[tot].id = tot;else q[tot].w ++;blg[i] = tot; //記錄i點(diǎn)是對(duì)應(yīng)去重后的哪個(gè)節(jié)點(diǎn)}cdq(1,tot);// f[i] 表示去重前點(diǎn)i滿足 (aj<=ai,bj<=bi,cj<=ci) 的j的個(gè)數(shù).// g[i] 表示去重后點(diǎn)i滿足條件的j的個(gè)數(shù)for(RG int i = 1; i <= tot; i ++)g[q[i].id] += q[i].w-1;for(RG int i = 1; i <= n; i ++)f[i] = g[blg[i]];for(RG int i = 1; i <= n; i ++)ans[f[i]] ++;for(RG int i = 0; i < n; i ++)printf("%lld\n",ans[i]);return 0; }離線修改與查詢問(wèn)題:樹(shù)狀數(shù)組 1
#include<bits/stdc++.h> #define RG register #define IL inline #define ll long long #define _ 4*500005 using namespace std;int n,m,ask,tot; ll ans[_];struct Do{int typ,pos,val;bool operator <(const Do &B)const{return (pos == B.pos)?typ < B.typ : pos < B.pos; } }; Do q[_],tmp[_];void cdq(RG int L,RG int R){if(L == R)return;RG int mid = (L+R)>>1; cdq(L,mid); cdq(mid+1,R);RG ll upt = 0 , l = L , r = mid+1 , oo = 0;while(l <= mid && r <= R){if(q[l] < q[r]){if(q[l].typ == 1)upt += q[l].val;tmp[++oo] = q[l++];}else {if(q[r].typ == 2)ans[q[r].val] -= upt;if(q[r].typ == 3)ans[q[r].val] += upt;tmp[++oo] = q[r++];}}while(l <= mid){if(q[l].typ == 1)upt += q[l].val;tmp[++oo] = q[l++];}while(r <= R){if(q[r].typ == 2)ans[q[r].val] -= upt;if(q[r].typ == 3)ans[q[r].val] += upt;tmp[++oo] = q[r++];}for(RG int i = L; i <= R; i ++)q[i] = tmp[i-L+1]; }int main(){scanf("%d %d",&n,&m);for(RG int i = 1,ww; i <= n; i ++)scanf("%d",&ww), q[++tot] = (Do){1,i,ww};ask = 0;for(RG int i = 1,tp,ps,ww; i <= m; i ++){scanf("%d %d %d",&tp,&ps,&ww);if(tp == 1)q[++tot] = (Do){1,ps,ww};elseq[++tot] = (Do){2,ps-1,++ask} ,q[++tot] = (Do){3,ww,ask};}cdq(1,tot);for(RG int i = 1; i <= ask; i ++)cout<<ans[i]<<endl;return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/Guess2/p/8367160.html
總結(jié)
以上是生活随笔為你收集整理的CDQ 分治算法模板的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 解决C/C++语言中全局变量重复定义的问
- 下一篇: Acess link