LibreOJ6279 數列分塊入門 3 題解

2022-05-19 22:07:28 字數 1537 閱讀 9644

題目描述

給出乙個長為 \(n\) 的數列,以及 \(n\) 個操作,操作涉及區間加法,詢問區間內小於某個值 \(x\) 的前驅(比其小的最大元素)。

輸入格式

第一行輸入乙個數字 \(n\)。

第二行輸入 \(n\) 個數字,第 \(i\) 個數字為 \(a_i\),以空格隔開。

接下來輸入 \(n\) 行詢問,每行輸入四個數字 \(opt\)、\(l\)、\(r\)、\(c\),以空格隔開。

若 \(opt=0\),表示將位於\([l,r]\) 之間的數字都加 \(c\)。

若 \(opt=1\),表示詢問 \([l,r]\) 中 \(c\) 的前驅的值(不存在則輸出 \(-1\))。

輸出格式

對於每次詢問,輸出一行乙個數字表示答案。

樣例輸入

4

1 2 2 3

0 1 3 1

1 1 4 4

0 1 2 2

1 1 2 4

樣例輸出
3

-1

資料範圍與提示

對於 \(100%\) 的資料,\(1 \le n \le 100000, -2^ \le others,ans \le 2^-1\)。

本題和《數列分塊入門 2》思路類似,同樣是開乙個陣列 \(b\) 並塊內排序,同樣是二分找 \(\le c\) 的最大值。

實現**如下:

#include using namespace std;

const int maxn = 100010;

int n, m, a[maxn], b[maxn], p[maxn], v[400], op, l, r, c;

inline void chk_max(int &a, int b)

void update_part(int pid)

void add(int l, int r, int c)

if (l % m != 1)

update_part(p[l]);

}else v[p[l]] += c;

if (r % m != 0)

else v[p[r]] += c;

for (int i = p[l]+1; i < p[r]; i ++)

v[i] += c;

}int pre_part(int pid, int c)

int get_pre(int l, int r, int c)

if (l % m != 1)

else chk_max(res, pre_part(p[l], c));

if (r % m != 0)

else chk_max(res, pre_part(p[r], c));

for (int i = p[l]+1; i < p[r]; i ++)

chk_max(res, pre_part(i, c));

return res;

}int main()

return 0;

}

LibreOJ 6279 數列分塊入門 3

題意 給你乙個n nn個整數的序列a aa,讓你進行兩種操作 分析 這裡用分塊 與第二題相似,查詢前驅我們同樣需要排序,不過這裡可能會想到這樣的情況,即對於查詢x xx前驅,如果查詢區間內有多個x,這樣顯然直接二分是不行的,即我們需要去重,或者統計區間內每個元素的個數,這裡便用到了set setse...

LOJ 6279 數列分塊3

題目大意 維護 n 個數組成的序列,支援兩種操作 區間加 區間查詢某個值的前驅 小於該值的最大值,若無前驅,輸出 1 題解1 可以像分塊2一樣,維護每個塊內元素的乙個有序序列,每次查詢時二分查詢即可。如下 include define pb push back define all x x.begi...

(分塊)LOJ 6279 數列分塊入門 3

傳送門 loj 6279.數列分塊入門 3 題意 給出乙個長為n的數列,以及n個操作,操作涉及區間加法,詢問區間內小於某個值x的前驅 比其小的最大元素 以下引用hzwer大佬的解答 n 100000其實是為了區分暴力和一些常數較大的寫法。接著第二題的解法,其實只要把塊內查詢的二分稍作修改即可。不過這...