LOJ 6278 數列分塊入門 2

2021-08-20 13:40:09 字數 1443 閱讀 2801

題意:給出乙個長為 n 的數列,以及 n個操作,操作涉及區間加法,詢問區間內小於某個值 x的元素個數。

思路:這裡有兩種操作,一種是區間加法,這在上一部落格已經介紹過了,不會的戳這裡,還有一種是區間查詢,因為每次查詢的數字都是不一樣的,所以要想時間最優化,必須要排序,因為排序後的查詢操作可以達到log的複雜度。

這裡運用hzwer大牛的話:

我們先來思考只有詢問操作的情況,不完整的塊列舉統計即可;而要在每個整塊內尋找小於乙個值的元素數,於是我們不得不要求塊內元素是有序的,這樣就能使用二分法對塊內查詢,需要預處理時每塊做一遍排序,複雜度o(nlogn),每次查詢在√n個塊內二分,以及暴力2√n個元素,總複雜度o(nlogn + n√nlog√n)。

有乙個小細節,關於block應該開多大,這裡因為用來vector,所以vector存的元素越多對時間越不利。

第一組是0.5n−

−√n

,第二組是n−

−√n

,第三組是2n−

−√n

可以很明顯看到,時間複雜度的優化還是很明顯的。

#include 

using

namespace

std;

const

int maxn = 5e4 + 5;

typedef

long

long ll;

int n, num, block, belog[maxn], opt, l, r, c;//belog[i]=j,表示a[i]屬於第j個分塊

int a[maxn], sum[maxn] ;//sum是整塊的加法標記

vector

v[maxn];//用於排序

inline

int read()

void reset(int x)

sort(v[x].begin(), v[x].end());

}void updata(int l, int r, int c)

reset(t2);//對最後乙個區間排序

}for(int i = t1 + 1; i <= t2 - 1; i++) sum[i] += c;//對整塊加上加法標記

}void query(int l, int r, ll c)

if(t1 != t2)

for(int i = t1 + 1; i <= t2 - 1; i++)

}printf("%d\n", ret);

}int main()

for(int i = 1; i <= belog[n]; i++)

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

return

0;}

loj 6278 數列分塊入門 2

題目 區間修改,詢問區間小於c的個數。分塊排序,用vector。至於那個塊的大小,好像要用到均值不等式 我不太會。就開始乙個個試,發現siz sqrt n 4時最快!明天去學一下算分塊複雜度的方法。include include include include include using names...

LOJ 6278 數列分塊入門 2

記憶體限制 256 mib時間限制 500 ms標準輸入輸出 題目型別 傳統評測方式 文字比較 上傳者 hzwer 提交提交記錄 統計討論 測試資料 題目描述 給出乙個長為 nnn 的數列,以及 nnn 個操作,操作涉及區間加法,詢問區間內小於某個值 的元素個數。輸入格式 第一行輸入乙個數字 nnn...

LOJ 6278 數列分塊入門 2

解題思路 分塊維護區間遞增序列。對於修改,邊界暴力後修改兩個邊界的遞增串行使其正確,完整塊打標記 對於詢問,邊界暴力 塊內二分 修改的複雜度 o sqrt n 2 sqrt n log sqrtn 詢問複雜度 o sqrt n 2 sqrt n 所以整體大概是 o q sqrt n log sqrt...