莫隊演算法 NBUT1457 Sona

2021-07-10 06:49:14 字數 1443 閱讀 7218

如果乙個問題可以簡單地描述為:對於乙個長度為n陣列,給出m個查詢,每個查詢為區間[l,r]。。。。

顯然,當l=1,r=n時該演算法的時間複雜度為o(n^2),但是通過莫隊演算法改變查詢的順序,我們能夠把時間複雜度降為o(n*√n),此處證明略去。

維護乙個當前的左右端點currentl和currentr,表示當前查詢到的位置,對於第i個查詢區間[l,r]暴力地將currentl和currentr分別移動到l和r,移動中經過的點執行相應的增加(add)或者刪除(del)操作。以上演算法還是o(n^2)的,因為查詢的順序可能雜亂無章。

把[1,n]分為sqrt(n)個區間,依次為1,2...,sqrt(n),每個區間有sqrt(n)個元素。所有查詢按照左端點所在的劃分區間的編號從小到大排序,編號相同的再按照右端點從小到大排序。按照排序完畢的順序依次查詢,演算法的時間複雜度就降為o(n*sqrt(n))

例如n = 9,m = 5的情況 9

1 2 2 5 6 8 5 7 3 5

4 52 3

1 41 2

8 9對查詢區間按劃分區間排序變為[1,4] [1,2] [2,3];[4,5];[8,9]

再次按照右端點劃分變為[1,2] [2,3] [1,4];[4,5];[8,9]

例題nbut1457 sona

給定n(1<=n<=10^5)個數,每個數在1~10^9以內,有q(1<=q<=10^5)個查詢。每次查詢輸出區間內每個數出現次數立方的和。

由於數的大小並不影響答案,我們需要先離散化。那麼每增添乙個數x進來ans=ans-(cnt[x]-1)^3+cnt[x]^3,刪除則相反。

#include#include#include#include#define maxn 100010

using namespace std;

typedef long long ll;

int a[maxn],d[maxn],block,n,q,len,cnt[maxn];

ll ans[maxn],now;

struct q

}que[maxn];

void init()

sort(a+1,a+n+1);

len = unique(a+1,a+n+1)-a;

for(int i = 1; i <= n; i++)

d[i] = lower_bound(a+1,a+len+1,d[i])-a;//d陣列記錄了離散化後a陣列的每個數

scanf("%d",&q);

for(int i = 0; i < q; i++)

sort(que,que+q);

}void add(int x)

void del(int x)

int main()

for(int i = 0; i < q; i++)

printf("%i64d\n",ans[i]);

}}

NBUT 1457 Sona(莫隊演算法)

題意 給定 n 105 的序列,q 105 次詢問 每次 詢問求 l,r 中每個數 字出現次 數的立方 和 分析 離散 化之後莫 隊模版題 vj抓題顯示64 位為ll d,藍兒 其實是i 64d,還 有謎之c e,模版 題坑的一 口老血。created by taosama on 2016 01 2...

NBUT 1457 Sona 莫隊演算法

題意 有n個數,有m個詢問,求每次詢問的區間 l,r 中,每種數字出現次數的立方和 分析 一開始不會莫隊演算法,結果想了很久,分析複雜度之後發現在轉移區間這一塊複雜度很大。後來發現莫隊演算法能很好解決這個問題。那麼就先說一下莫隊演算法吧,其實這個演算法還挺簡單的,能夠離線處理一類區間查詢不修改類問題...

NBUT 1457 莫隊演算法 離散化

題意 求出每乙個區間的能量值,能量值等於所有數字出現次數的三次方之和.很顯然離散化之後記錄下每乙個值出現的次數就能o 1 轉移了,刪除增加不難想.特別坑的是要用 int64,好像n個分數也要用 int64.include include include include include using n...