日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[摸鱼]cdq分治 学习笔记

發布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [摸鱼]cdq分治 学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

待我玩會游戲整理下思緒(分明是想摸魚

cdq分治是一種用于降維和處理對不同子區間有貢獻的離線分治算法

對于常見的操作查詢題目而言,時間總是有序的,而cdq分治則是耗費\(O(logq)\)的代價使動態操作化為靜態查詢問題(the world!

考慮無修改的求逆序對問題

每個元素可定義為\((pos_i,val_i)\),求對每個\((pos_i,val_i)\)有多少個\((pos_j,val_j)\),滿足\(pos_j<pos_i,val_j>val_i\)

cdq分治的過程就是令其中一維有序(pos),計算出貢獻消除該維度的影響,后面對已遍歷的元素只需得知\(val\)的關系即可

因此對于歸并過程的merge中假設\([l,mid]\)\([mid+1,r]\)的子區間已經統計完,保證了兩個子區間分別有序,那只需再求左子區間對右子區間的貢獻即可

比如左子區間中的下標\(p\)和右子區間中的下標\(q\)滿足\(val_p>val_q\),那么可以得出\(val_{[p...mid]}>val_q\),左區間對于右區間中的\(q\)的貢獻為\(mid-p+1\),統計完后繼續維護大區間的有序并pushup即可

而對于有修改(既存在時間變量)的操作,我們需要維護左子區間的修改對右區間查詢的影響(因為對于分治,左區間存在是右區間存在的前提),對于查詢則需要標記時間的維度\(ansid\)

注意如果\(p\)\(q\)優先越界的處理上的不同

以及區間查詢時一分為二的做法


練手題 Luogu - P3374

題意:m次操作,單點更新,區間查詢

我們把原數組的初始值當作插入修改來處理,時間復雜度\(O((m+n)log(m+n))\)

#include<bits/stdc++.h> #define rep(i,j,k) for(register int i=j;i<=k;i++) #define rrep(i,j,k) for(register int i=j;i>=k;i--) #define erep(i,u) for(register int i=head[u];~i;i=nxt[i]) #define print(a) printf("%lld",(ll)(a)) #define printbk(a) printf("%lld ",(ll)(a)) #define println(a) printf("%lld\n",(ll)(a)) using namespace std; const int MAXN = 1.5e6+11; typedef long long ll; const ll MOD = 1e9+7; const ll INF = 1ll<<60; unsigned int SEED = 19260817; ll read(){ll x=0,f=1;register char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; }struct QUERY{int pos,val,type;bool operator < (const QUERY &rhs) const{if(pos!=rhs.pos) return pos<rhs.pos;return type<rhs.type;} }Q[MAXN],tmp[MAXN]; ll ans[MAXN]; void solve(int l,int r){if(l==r)return;int mid=l+r>>1;solve(l,mid);solve(mid+1,r);int p=l,q=mid+1,cnt=0;ll sum=0;while(p<=mid&&q<=r){if(Q[p]<Q[q]){if(Q[p].type==1) sum+=Q[p].val;tmp[++cnt]=Q[p++];}else{if(Q[q].type==2) ans[Q[q].val]-=sum;if(Q[q].type==3) ans[Q[q].val]+=sum;tmp[++cnt]=Q[q++];}}while(p<=mid) tmp[++cnt]=Q[p++];while(q<=r){if(Q[q].type==2) ans[Q[q].val]-=sum;if(Q[q].type==3) ans[Q[q].val]+=sum;tmp[++cnt]=Q[q++];}rep(i,1,cnt) Q[i+l-1]=tmp[i]; } int main(){int m,n;while(cin>>n>>m){int cnt=0,ansid=0;rep(i,1,n){Q[++cnt].pos=i;Q[cnt].val=read();Q[cnt].type=1;}rep(i,1,m){int op=read();if(op==1){Q[++cnt].pos=read();Q[cnt].val=read();Q[cnt].type=1;}else{int l=read();int r=read();Q[++cnt].pos=l-1;Q[cnt].val=++ansid;Q[cnt].type=2;Q[++cnt].pos=r;Q[cnt].val=ansid;Q[cnt].type=3;}}solve(1,cnt);rep(i,1,ansid) println(ans[i]);}return 0; }

轉載于:https://www.cnblogs.com/caturra/p/9387626.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的[摸鱼]cdq分治 学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。