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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

分治 —— 莫队算法 —— 带修莫队

發布時間:2025/3/17 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分治 —— 莫队算法 —— 带修莫队 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【概述】

普通莫隊由于強制離線是不能修改的,但對于強制在線的題,可以在普通莫隊的基礎上強行加上一維時間軸 time,表示這次操作的時間,即在每個詢問前已經完成了多少次修改。

簡單來說,就是將詢問 [l,r],變為 [l,r,time],那么指針也可在時間維度上移動,使得第一關鍵字是左端點所在的塊,第二關鍵字是右端點所在的塊,第三關鍵字是時間,即 [l,r,time] 多了一維可移動的方向:

  • [l-1,r,time]
  • [l+1,r,time]
  • [l,r-1,time]
  • [l,r+1,time]
  • [l,r,time-1]
  • [l,r,time+1]
int l=1,r=0,time=0; for(int i=1;i<=m;++i){int ql=q[i].l,qr=q[i].r;//詢問的左右端點int qtime=q[i].time;//詢問的時間軸while(l>ql) add(--l);//[l-1,r,time]while(l<ql) del(l++);//[l+1,r,time]while(r<qr) add(++r);//[l,r+1,time]while(r>qr) del(r--);//[l,r-1,time]while(time<qtime) change(i,++time);//[l,r,time+1]while(time>qtime) change(i,time--);//[l,r,time-1]res[q[i].id]=ans;//獲取答案 }

暴力查詢時,如果當前修改數比詢問的修改數少就把沒修改的進行修改,反之回退,需要注意的是,修改分為兩部分:

  • 若修改的位置在當前區間:更新答案
  • 無論修改的位置是否在當前區間:都要進行修改,以供 add 和 del 函數在以后更新答案
struct Change{int pos;//要修改的位置int col;//要改成的值 }c[N]; void add(int x){...}//統計新的,根據具體情況修改 void del(int x){...}//減去舊的,根據具體情況修改 void change(int x,int ti){//改變時間軸if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r){del(a[c[ti].pos]);//刪除指定位置上的值add(c[ti].col);//統計新的數}swap(c[ti].col,a[c[ti].pos]);//直接互換,下次執行時必定是回退這次操作 } /*change函數會執行或回退修改ti,執行還是回退取決于是否執行過,x表明當前的詢問是x,即若修改了區間[q[x].l,q[x].r],便要更新答案 */

【排序】

由于第一關鍵字是左端點所在的塊,第二關鍵字是右端點所在的塊,第三關鍵字是時間,雖然多了一個維度,但轉移仍是 O(1) 的復雜度,只需要在排序時考慮 time 的影響即可。

  • 當左右端點在同一個塊中:以 time 為關鍵字排序
  • 當左端點在同一個塊中,右端點不在:以右端點為關鍵字排序
  • 當左端點不在同一個塊:以左端點為關鍵字排序
bool cmp(Node a,Node b){//排序if( (a.l/block)==(b.l/block) ){//當左端點位于同一個塊時if( (a.r/block)==(b.r/block) )//當右端點位于同一個塊時return a.time<b.time;elsereturn a.r<b.r;}else//當左端點不位于同一個塊時return a.l<b.l;//return (a.l/block)^(b.l/block) ? a.l<b.l : ( ((a.r/block)^(b.r/block))?a.r<b.r:a.time<b.time ); }

【分塊與時間復雜度】

設 block?為分塊大小,c 為修改個數,q 為詢問個數,l、r 塊表示以 l/block、r/block?分的塊,每個 l 塊包含 n/block 個 r 塊

  • 對于時間指針 time,每個 r 塊最多會移動 c 次,共有??個 r 塊,總移動次數為?
  • 對于左端點指針 l:l 塊內最多移動 block 次,換 l 塊時最多移動 2*block 次,總移動次數為:
  • 對于右端點指針 r:總移動次數為:
    • r 塊內最多移動 block 次,換 r 塊時最多移動 2*block 次,所有 l 塊內移動次數之和為?
    • 換 l 塊時最多移動 n 次,總的換 l 塊時移動次數之和為?

故總移動次數為:,因而總時間復雜度為?

由于一般題目不會分別告訴修改與詢問的個數,統一用 m 表示,則有:

通過 Mathermatica 軟件分析,要想讓總時間復雜度最小,可以得到 block 的取值如下:

由于式子過于復雜,難以寫出帶修莫隊的最佳分塊數,因此一般視作 n=m,即有:

令總時間復雜度最小,可得到當??時最小,此時總時間復雜度為:

綜上,分塊一般以??為一塊,分成? 個塊,總時間復雜度為:

int block=pow(n,0.66666);

?【模版】

struct Node{int l,r;//詢問的左右端點int time;//時間維度int id;//詢問的編號 }q[N]; struct Change{int pos;//要修改的位置int col;//要改成的值 }c[N]; int n,m,a[N]; int block;//分塊 int numQ,numC;//查詢、修改操作的次數 LL ans,cnt[N]; LL res[N];bool cmp(Node a,Node b){//排序return (a.l/block)^(b.l/block) ? a.l<b.l : ((a.r/block)^(b.r/block)?a.r<b.r:a.time<b.time); }void add(int x){//統計新的,根據具體情況修改if(cnt[x]==0)ans++;cnt[x]++;} void del(int x){//減去舊的,根據具體情況修改cnt[x]--;if(cnt[x]==0)ans--; } void change(int x,int ti){//改變時間軸if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r){del(a[c[ti].pos]);//刪除指定位置上的值add(c[ti].col);//統計新的數}swap(c[ti].col,a[c[ti].pos]);//直接互換,下次執行時必定是回退這次操作 } int main(){while(scanf("%d%d",&n,&m)!=EOF){ans=0;numQ=0;numC=0;memset(cnt,0,sizeof(cnt));block=pow(n,0.66666);//分塊for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=m;i++){char op[10];scanf("%s",op);if(op[0]=='Q'){//查詢操作++numQ;//查詢操作次數+1scanf("%d%d",&q[numQ].l,&q[numQ].r);q[numQ].id=numQ;//序號q[numQ].time=numC;//時間軸}else{//修改操作++numC;//修改操作次數+1scanf("%d%d",&c[numC].pos,&c[numC].col);}}sort(q+1,q+numQ+1,cmp);//對詢問進行排序int l=1,r=0,time=0;//左右指針與時間軸for(int i=1;i<=numQ;i++){int ql=q[i].l,qr=q[i].r;//詢問的左右端點int qtime=q[i].time;//詢問的時間軸while(l>ql) add(a[--l]);//[l-1,r,time]while(l<ql) del(a[l++]);//[l+1,r,time]while(r<qr) add(a[++r]);//[l,r+1,time]while(r>qr) del(a[r--]);//[l,r-1,time]while(time<qtime) change(i,++time);//[l,r,time+1]while(time>qtime) change(i,time--);//[l,r,time-1]res[q[i].id]=ans;//獲取答案}for(int i=1;i<=numQ;i++)printf("%lld\n",res[i]);}return 0; }

?

總結

以上是生活随笔為你收集整理的分治 —— 莫队算法 —— 带修莫队的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 懂色av一区二区三区免费 | av官网在线观看 | 中文字幕精品一区二 | 东北少妇不戴套对白第一次 | 超碰网站在线 | 免费看黄的网址 | 国产在线精品一区二区三区 | 国产wwwxxx| 色葡萄影院 | 国产日韩欧美精品在线 | 日韩中文在线播放 | 狠狠做深爱婷婷久久综合一区 | 欧洲精品一区二区三区 | 亚洲精品www. | 中国少妇初尝黑人巨大 | 欧美性开放视频 | 国产一二三视频 | 国产又黄又猛 | 天天操夜操 | 亚洲国产精品毛片 | 国产成人三级在线 | 国产欧美日韩精品在线观看 | 99免费在线 | 欧美日韩国产一级 | 久色免费视频 | v888av| 一区二区三区中文字幕 | 松本一香在线播放 | 午夜激情在线观看 | 热久久中文字幕 | 九久久久久 | 亚洲熟妇无码爱v在线观看 九色福利 | 欧美性生活网站 | 国产又黄又硬又粗 | 色婷婷av一区二区三 | 在线视频中文字幕 | 久久国产成人 | 麻豆精品在线看 | 国产福利99| 姐姐你真棒插曲快来救救我电影 | 黄色片网站在线免费观看 | 欧美色涩在线第一页 | 人体av| 亚洲成人1区 | 欧美呦呦 | 国产精品麻豆一区二区 | 男女靠逼视频 | 中文字幕无码精品亚洲35 | 久久久久久久久久国产精品 | 欧美婷婷六月丁香综合色 | 少妇高潮一区二区三区 | 就要操av | 日韩美女中文字幕 | 天天色成人网 | 亚洲天堂视频在线观看 | 亚洲国产99 | 久久av综合 | 波多野结衣成人在线 | 丹丹的呻吟声1一7 | 狠狠撸狠狠干 | 成年人黄色录像 | 中文字幕在线观看的网站 | 久久亚洲成人 | 果冻传媒18禁免费视频 | 亚洲17p| 黄色永久视频 | 国产又黄又粗又猛又爽视频 | 久久av高潮av无码av喷吹 | xxxx国产视频 | 林雅儿欧洲留学恋爱日记在线 | 拔插拔插海外华人免费视频 | 久久久久久91亚洲精品中文字幕 | 麻豆影视在线 | 国产高清一区在线观看 | 国产成人传媒 | 色在线影院 | 欧美午夜在线视频 | 久久中文网 | 99爱视频在线观看 | 色欲久久久天天天综合网 | hd丰满圆润的女人hd | 国产精品99久久久久久久久久久久 | 久久婷婷丁香 | 亚洲欧美日韩一区二区 | 国产美女黄色 | 欧美xxxⅹ性欧美大片 | 欧美国产在线观看 | 久久久噜噜噜久久久 | 日本大尺度吃奶做爰视频 | 色人阁婷婷 | 91精品毛片 | 亚洲一区偷拍 | japanesehdxxxx| 欧美日韩一级视频 | 国产三级精品三级在线观看 | 午夜视频 | 久久久精品久久久 | 日韩成人av一区二区 | 亚洲一区二区三区婷婷 |