NBUT 1457 Sona 莫隊演算法

2022-05-19 01:23:50 字數 1777 閱讀 9474

題意:有n個數,有m個詢問,求每次詢問的區間[l,r]中,每種數字出現次數的立方和

分析:一開始不會莫隊演算法,結果想了很久,分析複雜度之後發現在轉移區間這一塊複雜度很大。

後來發現莫隊演算法能很好解決這個問題。

那麼就先說一下莫隊演算法吧,其實這個演算法還挺簡單的,能夠離線處理一類區間查詢不修改類問題。如果知道[l,r]的答案,那麼也可通過計算得到[l-1,r],[l-1,r+1],[l,r-1],[l,r+1]四個區間的答案,複雜度是o(1)。

莫隊演算法本質是在暴力上進行了改良,離線儲存所有的查詢,然後以一定的順序進行排序,然後通過區間的變化來得到答案,減少了區間移動幅度過大帶來的時間複雜度。至於用什麼排序,一般採用的排序方法就是把長度為n的區間分為block=sqrt(n)份,然後把所有區間[l,r]以 l/block 為第一基準,以r為第二基準進行二級排序。然後要注意區間是先擴大還是先縮小,不同的題目處理不同。

這道題的話,是要計算乙個區間內每種數出現次數的立方和,那麼轉移的話,假設乙個區間是[l,r],如果向左轉移,用ans儲存區間的答案,cnt[i]記錄第 i 種數出現的次數,那麼假設向左轉移新加進區間的數字是a,由於a新加進區間,cnt[a]++,ans=ans-(cnt[a]-1)^3+(cnt[a])^3。數字移除區間反之。

#pragma comprint(linker, "/stack:1024000000,1024000000")#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll __int64

#define fin freopen("in.txt","r",stdin)

using

namespace

std;

const

int maxn=100000+5

;int

block;

struct

node

bool

operator

}po[maxn];

intn,q;

inta[maxn],b[maxn];

ll cnt[maxn],ans[maxn],lastans;

ll calc(ll x)

void update(int pos,int

x)int

main()

sort(b+1,b+n+1

);

int sz=unique(b+1,b+n+1)-b;

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

//離散化

scanf("

%d",&q);

block=sqrt(n+0.5); //

分塊for(int i=0;i)

sort(po,po+q);

int lastl=2,lastr=1

; lastans=0

; memset(cnt,

0,sizeof

(cnt));

for(int i=0;i)

for (int i=0;i)

printf(

"%i64d\n

",ans[i]);

}return0;

}

view code

NBUT 1457 Sona(莫隊演算法)

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

莫隊演算法 NBUT1457 Sona

如果乙個問題可以簡單地描述為 對於乙個長度為n陣列,給出m個查詢,每個查詢為區間 l,r 顯然,當l 1,r n時該演算法的時間複雜度為o n 2 但是通過莫隊演算法改變查詢的順序,我們能夠把時間複雜度降為o n n 此處證明略去。維護乙個當前的左右端點currentl和currentr,表示當前查...

NBUT 1457 Sona(莫隊演算法 離散化)

莫隊演算法就是能用n sqrt n 的時間來解決無修改區間查詢的一種辦法 主要處理就是把詢問暫時不按照讀入順序而按照所在塊和右端點值為關鍵字進行排序,然後對這樣的乙個暫時非正常的詢問順序進行計算回答,然後可以再次按照輸入順序排序或者用陣列記錄答案後輸出。可以參考這篇部落格 莫隊演算法經典例題 這題寫...