Topic link https://loj.ac/problem/6278
Memory limit: 256 MiB time limit: 500 ms
Topic Description
Given a long n sequence and n operations involving interval addition, the number of elements less than a certain value x in the interval is asked.
Input format
The first line enters a number.
In the second line, n digits are entered, and the number i is ai, separated by spaces.
Next, enter n lines of inquiry, each line with four numbers opt,l,r,c separated by spaces.
If pot =0, the number between [l,r] is added.
If opt =1, it means the number of numbers less than c^2 in the query [l,r].
Output format
For each query, output a line of numbers to indicate the answer.
Example
sample input
4 1 2 2 3 0 1 3 1 1 1 3 2 1 1 4 1 1 2 3 2
sample output
3 0 2
Data Scope and Tips
For 100% data 1 <= n <= 50000, -2 ^ 31 <= others, ans <= 2 ^ 31 - 1.
This problem is similar to the previous one, but one operation is more difficult to complete, that is, to find the number of intervals less than x.
According to the consistency of partitioning, we first divide the sequence into sqrt(n) blocks, a n d then calculate the end points of the blocks and the blocks to which each point belongs. Here we copy a with another array D.
int n; cin >> n; int t = sqrt(n); for (int i = 1; i <= n; i++) cin >> a[i], d[i] = a[i]; for (int i = 1; i <= t; i++) { L[i] = (i - 1) * t + 1; R[i] = i * t; } if (R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n; for (int i = 1; i <= t; i++) for (int j = L[i]; j <= R[i]; j++) id[j] = i;
What are we going to do next? Of course, each block is ordered:
for (int i = 1; i <= t; i++) sort(d + L[i], d + R[i] + 1);
After this operation, the elements in each block are ordered without affecting the original array.
Next is the conventional operation. For update, we add one more operation on the basis of block 1:
int ll = id[l], rr = id[r]; for (int i = l; i <= R[ll]; i++) a[i] += w; for (int i = L[ll]; i <= R[ll]; i++) d[i] = a[i]; sort(d + L[ll], d + R[ll] + 1);
That is to say, the order of the elements of the block to which l belongs is disrupted, and we need to reorder it. For blocks that do not belong to L and r, we do not need to do anything, because the size relationship of each element in the block plus the same number is invariable.
So it's the same when inquiring. For violent inquiries of blocks belonging to l and r, and blocks between l and r, because they are orderly, we just need to find the first one larger than or equal to him, so we can divide it into two parts.
for (int i = ll + 1; i <= rr - 1; i++) { int x = w - add[i]; ans += lower_bound(d + L[i], d + R[i] + 1, x) - (d + L[i]); }
The following is the AC code:
#include <bits/stdc++.h> using namespace std; const int mac = 5e4 + 10; int a[mac], add[300], id[mac], L[mac], R[mac]; int d[mac]; void update(int l, int r, int w) { int ll = id[l], rr = id[r]; if (ll == rr) { for (int i = l; i <= r; i++) a[i] += w; for (int i = L[ll]; i <= R[ll]; i++) d[i] = a[i]; sort(d + L[ll], d + R[ll] + 1); } else { for (int i = l; i <= R[ll]; i++) a[i] += w; for (int i = L[ll]; i <= R[ll]; i++) d[i] = a[i]; sort(d + L[ll], d + R[ll] + 1); for (int i = ll + 1; i <= rr - 1; i++) add[i] += w; for (int i = L[rr]; i <= r; i++) a[i] += w; for (int i = L[rr]; i <= R[rr]; i++) d[i] = a[i]; sort(d + L[rr], d + R[rr] + 1); } } int query(int l, int r, int w) { int ll = id[l], rr = id[r]; int ans = 0; if (ll == rr) { for (int i = l; i <= r; i++) if (a[i] + add[ll] < w) ans++; } else { for (int i = l; i <= R[ll]; i++) if (a[i] + add[ll] < w) ans++; for (int i = L[rr]; i <= r; i++) if (a[i] + add[rr] < w) ans++; for (int i = ll + 1; i <= rr - 1; i++) { int x = w - add[i]; ans += lower_bound(d + L[i], d + R[i] + 1, x) - (d + L[i]); } } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; int t = sqrt(n); for (int i = 1; i <= n; i++) cin >> a[i], d[i] = a[i]; for (int i = 1; i <= t; i++) { L[i] = (i - 1) * t + 1; R[i] = i * t; } if (R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n; for (int i = 1; i <= t; i++) for (int j = L[i]; j <= R[i]; j++) id[j] = i; for (int i = 1; i <= t; i++) sort(d + L[i], d + R[i] + 1); for (int i = 1; i <= n; i++) { int opt, l, r, c; cin >> opt >> l >> r >> c; if (opt) { int ans = query(l, r, c * c); cout << ans << endl; } else update(l, r, c); } return 0; }