日韩性视频-久久久蜜桃-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; }

?

總結

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

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

主站蜘蛛池模板: 91av免费| 丰满熟妇人妻av无码区 | 国产精品综合在线 | 欧美老熟妇xb水多毛多 | 男人操女人下面视频 | 国产香蕉尹人视频在线 | 原创真实夫妻啪啪av | 三级视频在线观看 | 91综合视频| 亚洲国产精品成人综合色在线婷婷 | 欧美一区三区二区在线观看 | 欧美综合专区 | 久久精品一二区 | 五月天六月色 | 激情丁香婷婷 | 三级av网址 | 久久一区二区三区四区 | 一级黄色网址 | 美丽的姑娘观看在线播放 | 欧美性受视频 | 国产中文字幕视频 | 视频在线观看91 | 一区二区三区视频网站 | 欧美一级色| 怡春院一区二区 | 国偷自产视频一区二区久 | 亚洲白浆| 欧美性视频一区二区 | 欧美激情区 | 国产成人午夜精华液 | 伊人久久精品 | 男生插女生的网站 | 男人的天堂黄色 | 国产电影一区二区三区 | 自拍偷拍视频在线 | 手机av免费 | 久久久久久艹 | 奇米影视av | 美日韩成人av | 六月天综合网 | 日韩黄页网站 | yy6080午夜 | 99re视频 | 无码精品国产一区二区三区 | 波多野结衣欧美 | 国产欧美日韩综合精品一区二区 | 久久久国产成人 | 日本黄色视 | 黄色www| 尤物视频官网 | 黄色小视频免费看 | 久久国产精品精品国产色婷婷 | 妓院一钑片免看黄大片 | 一区二区三区国产精品视频 | 一本一道久久a久久 | 日韩精品短片 | 男操女视频在线观看 | 亚洲精品亚洲人成人网 | 天天在线观看 | 国产在线播放一区二区 | 青草青青视频 | 成人www视频 | 欧洲av在线 | 一级免费黄色片 | 亚洲精品国产精品国 | 中文字幕亚洲在线观看 | 国产第一页视频 | 成人久久久精品乱码一区二区三区 | 麻豆精品一区二区三区 | 91国内揄拍国内精品对白 | 中文一区视频 | 91亚洲视频 | 91九色高潮 | 亚洲午夜精品福利 | 99久久久无码国产精品性 | 999www| 精品人妻大屁股白浆无码 | 免费无码毛片一区二三区 | 久久久久亚洲av成人人电影 | 久久久久久久久久久久97 | 国产精品视频一区二区三区不卡 | 久久久精品视频在线 | 亚洲中文字幕在线观看 | 黄色激情毛片 | 亚洲一区二区三区无码久久 | videos亚洲 | 欧美黄视频在线观看 | 99草视频 | 空姐吹箫视频大全 | 色婷婷六月天 | 884aa四虎影成人精品一区 | 日日夜夜操操 | 视频在线播 | 99青草 | 色人阁五月天 | 免费爱爱网址 | 热久久最新 | 亚洲成人日韩在线 | 亚洲精品国产一区二 |