数据结构题(莫队算法)
數(shù)據(jù)結(jié)構(gòu)題
題目:
問(wèn)在區(qū)間[l,r]和[l1,r1]內(nèi)x的出現(xiàn)次數(shù)的乘積是多少?
題解:
莫隊(duì)算法的模板題
關(guān)于莫隊(duì)算法你可以參考這個(gè)
我這里簡(jiǎn)單的說(shuō)說(shuō)我對(duì)莫隊(duì)的理解:
莫隊(duì)是一個(gè)優(yōu)雅的暴力,就是將原本復(fù)雜度不能過(guò)的程序進(jìn)行優(yōu)化,莫隊(duì)是通過(guò)分塊來(lái)實(shí)現(xiàn)
如果暴力做這個(gè)題,查詢區(qū)間[l,r]內(nèi)x的數(shù)量我們可能就從頭開(kāi)始搜查,按照題目給的數(shù)據(jù)來(lái)搜查,但其實(shí)我們可以這樣優(yōu)化,比如題目給的查詢區(qū)間[3,4],[2,4],[1,5],我們可以先查詢[1,5],然后順勢(shì)查詢[2,4],最后[3,4],而非從頭開(kāi)始,這樣就省了不少時(shí)間。那如何實(shí)現(xiàn)這個(gè)?我們可以對(duì)整體進(jìn)行分塊,然后按照所分的快進(jìn)行排序,盡可能實(shí)現(xiàn)查詢區(qū)間時(shí)省時(shí)省力,最后再輸出答案
至于為什么要分塊排序呢?可以看看莫隊(duì)算法的講解
很顯然這是一個(gè)離線算法,且適合查詢量很大的情況
代碼如下
代碼:
#include<bits/stdc++.h> #define forn(i,a,b) for(ll i=a;i<=b;i++) #define INF 0x3f3f3f3f using namespace std;#define ll long long const ll N =100*1000+10; const ll mod = 20180623; ll n,m; ll a[N],ans[N*2],num[N],pos[N]; struct node{ll L,R,x,id; }t[N*2];bool cmp(node a,node b){if(pos[a.L]==pos[b.L])return a.R<b.R;else return pos[a.L]<pos[b.L]; }ll L=1,R=0; void solve(node p){while(p.L>L){num[a[L]]--;L++;}while(p.R>R){R++;num[a[R]]++;}while(p.L<L){L--;num[a[L]]++;}while(p.R<R){num[a[R]]--;R--;} }int main(){scanf("%lld %lld",&n,&m);memset(num,0,sizeof(num));ll block=sqrt(n);for(ll i=1;i<=n;i++){scanf("%lld",a+i);pos[i]=i/block;}for(ll i=1;i<=m;i++){ll l1,r1,l2,r2,x;scanf("%lld%lld%lld%lld%lld",&l1,&r1,&l2,&r2,&x);if(l1>r1)swap(l1,r1);if(l2>r2)swap(l2,r2);t[i].L=l1;t[i].R=r1;t[i].id=i;t[i].x=x;t[i+m].L=l2;t[i+m].R=r2;t[i+m].id=i+m;t[i+m].x=x;}sort(t+1,t+1+2*m,cmp);memset(num,0,sizeof(num));for(ll i=1;i<=2*m;i++){solve(t[i]);ans[t[i].id]=num[t[i].x];}for(ll i=1;i<=m;i++)printf("%lld\n%lld\n%lld\n",ans[i]%mod,ans[i+m]%mod,(ans[i]%mod*ans[i+m])%mod);return 0; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的数据结构题(莫队算法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 祖母绿是什么 祖母绿介绍
- 下一篇: Gensee SDK RoleType详