題目描述
給出乙個長為 \(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其實是為了區分暴力和一些常數較大的寫法。接著第二題的解法,其實只要把塊內查詢的二分稍作修改即可。不過這...