int len = sqrt(n); vector<i64> a(n + 1), b(n + 1), id(n + 1), g(n + 1), cnt(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; id[i] = (i - 1) / len + 1; b[i] = a[i]; }
auto work = [&](int id) -> void { int st = 1 + (id - 1) * len; for (int i = st; i < min(n + 1, st + len); i++) { b[i] = a[i]; } sort(b.begin() + st, min(b.end(), b.begin() + st + len)); };
for (int i = 1; i <= n; i += len) { work(id[i]); }
auto add = [&](int l, int r, i64 c) -> void { if (id[l] == id[r]) { for (int i = l; i <= r; i++) { a[i] += c; } work(id[l]); } else { for (int i = l; id[l] == id[i]; i++) { a[i] += c; } work(id[l]);
for (int i = r; id[r] == id[i]; i--) { a[i] += c; } work(id[r]);
for (int i = id[l] + 1; i < id[r]; i++) { g[i] += c; } } };
auto query = [&](int l, int r, i64 c) -> int { if (id[l] == id[r]) { int sum = 0; for (int i = l; i <= r; i++) { if (a[i] + g[id[i]] < c) { sum++; } } return sum; } else { int sum = 0; for (int i = l; id[i] == id[l]; i++) { if (a[i] + g[id[i]] < c) { sum++; } } for (int i = r; id[i] == id[r]; i--) { if (a[i] + g[id[i]] < c) { sum++; } }
for (int i = id[l] + 1; i < id[r]; i++) { int l = 1 + (i - 1) * len, r = i * len; int ls = l; while (l <= r) { int mid = (l + r) >> 1; if (g[id[mid]] + b[mid] < c) { l = mid + 1; } else { r = mid - 1; } } int res = max(0, r - ls + 1); sum += res; } return sum; } };
for (int i = 1; i <= n; i++) { i64 opt, l, r, c; cin >> opt >> l >> r >> c;
if (opt == 0) { add(l, r, c); } else { cout << query(l, r, c * c) << '\n'; } }
return0; }
三. 区间加法,询问区间内小于某个值 x 的前驱(比其小的最大元素)。
题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,询问区间内小于某个值 x 的前驱(比其小的最大元素)。
输入格式
第一行输入一个数字 n。
第二行输入 n 个数字,第 i 个数字为 a_i,以空格隔开。
接下来输入 n 行询问,每行输入四个数字 \mathrm{opt}、l、r、c,以空格隔开。
若 \mathrm{opt} = 0,表示将位于 [l, r] 的之间的数字都加 c。
若 \mathrm{opt} = 1,表示询问 [l, r] 中 c 的前驱的值(不存在则输出 -1)。
i64 len = sqrt(n); vector<i64> a(n + 1), b(n + 1), g(n + 1), id(n + 1); for (i64 i = 1; i <= n; i++) { cin >> a[i]; id[i] = (i - 1) / len + 1; }
auto work = [&](i64 id) -> void { i64 st = 1 + (id - 1) * len; for (i64 i = st; i < min(n + 1, st + len); i++) { b[i] = a[i]; } sort(b.begin() + st, min(b.end(), b.begin() + st + len)); };
for (int i = 1; i <= n; i += len) { work(id[i]); }
auto add = [&](i64 l, i64 r, i64 c) -> void { if (id[l] == id[r]) { for (i64 i = l; i <= r; i++) { a[i] += c; } work(id[l]); } else { for (i64 i = l; id[i] == id[l]; i++) { a[i] += c; } work(id[l]);
for (i64 i = r; id[i] == id[r]; i--) { a[i] += c; } work(id[r]);
for (i64 i = id[l] + 1; i < id[r]; i++) { g[i] += c; } } };
auto query = [&](i64 l, i64 r, i64 c) -> i64 { if (id[l] == id[r]) { i64 ans = -1; for (i64 i = l; i <= r; i++) { if (a[i] + g[id[i]] < c) { ans = max(ans, a[i] + g[id[i]]); } } return ans; } else { i64 ans = -1; for (i64 i = l; id[l] == id[i]; i++) { if (a[i] + g[id[i]] < c) { ans = max(ans, a[i] + g[id[i]]); } }
for (i64 i = r; id[i] == id[r]; i--) { if (a[i] + g[id[i]] < c) { ans = max(ans, a[i] + g[id[i]]); } }
for (i64 i = id[l] + 1; i < id[r]; i++) { i64 l = 1 + (i - 1) * len, r = i * len; i64 mid; while (l <= r) { mid = (l + r) >> 1; if (b[mid] + g[id[mid]] < c) { ans = max(ans, b[mid] + g[id[mid]]); l = mid + 1; } else { r = mid - 1; } } } return ans; } };
for (i64 i = 1; i <= n; i++) { i64 opt, l, r, c; cin >> opt >> l >> r >> c;
vector<i64> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; } int len = sqrt(n); int siz = n / len + ((n % len) ? 1 : 0); //cerr << siz << '\n'; vector<i64> b(n + 1), id(n + 1), c(siz + 1), ov(siz + 1); for (int i = 1; i <= n; i++) { id[i] = (i - 1) / len + 1; c[id[i]]++; b[id[i]] += a[i]; }
for (int i = 1; i <= n; i++) { if (a[i] == 1) { ov[id[i]]++; } }
auto f = [&](int l, int r) -> void { if (id[l] == id[r]) { for (int i = l; i <= r; i++) { if (a[i] != 1) { b[id[i]] -= a[i]; a[i] = (i64)sqrt(a[i]); b[id[i]] += a[i];
if (a[i] == 1) { ov[id[i]]++; } } } return; } for (int i = l; id[i] == id[l]; i++) { if (a[i] != 1) { b[id[i]] -= a[i]; a[i] = (i64)sqrt(a[i]); b[id[i]] += a[i];
if (a[i] == 1) { ov[id[i]]++; } } }
for (int i = r; id[i] == id[r]; i--) { if (a[i] != 1) { b[id[i]] -= a[i]; a[i] = (i64)sqrt(a[i]); b[id[i]] += a[i];
if (a[i] == 1) { ov[id[i]]++; } } }
for (int i = id[l] + 1; i < id[r]; i++) { if (ov[i] != c[i]) { //cerr << "F:" << i << ' '; for (int j = 1 + (i - 1) * len; j <= i * len; j++) { //cout << id[j] << '\n'; if (a[j] != 1) { b[id[j]] -= a[j]; a[j] = (int)sqrt(a[j]); b[id[j]] += a[j];
if (a[j] == 1) { ov[id[j]]++; } } } } } };
auto query = [&](int l, int r) -> i64 { if (id[l] == id[r]) { i64 ans = 0; for (int i = l; i <= r; i++) { ans += a[i]; } return ans; } i64 res = 0; for (int i = l; id[i] == id[l]; i++) { res += a[i]; }
for (int i = id[l] + 1; i < id[r]; i++) { res += b[i]; }
for (int i = r; id[i] == id[r]; i--) { res += a[i]; }
return res; };
for (int i = 1; i <= n; i++) { int opt, l, r, c; cin >> opt >> l >> r >> c;