Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ∧_∧
- ( ・ω・。)つ━☆・*。
- ⊂ ノ ・゜
- しーJ Accepted
- */
- // #pragma GCC optimize("O3")
- // #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
- #include <bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- #define ll long long
- #define all(x) begin(x), end(x)
- #define x first
- #define y second
- // #define int long long
- using namespace std;
- using namespace __gnu_pbds;
- typedef long double ld;
- template<typename T>
- using kawaii_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
- const ld PI = atan2(0, -1);
- void seriy() {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- cout << fixed << setprecision(14);
- #ifdef _offline
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- }
- const int MAXN = 1e6 + 10;
- const int MAXM = 600;
- const int INF = 1e9 + 7;
- const int BASE = 47;
- const int MOD = 1e9 + 7;
- const int MAXLOG = 51;
- const ld EPS = 1e-6;
- struct node {
- int mx, pos;
- };
- struct rq {
- int l, r, num;
- };
- vector<node> t(4 * MAXN, {-INF, INF});
- int cur = 1;
- int n, q, k;
- node get(int v, int tl, int tr, int l, int r) {
- if(tl > r || tr < l) {
- return {-INF, INF};
- }
- if(tl >= l && tr <= r) {
- return t[v];
- }
- int tm = (tl + tr) >> 1;
- node left = get(v * 2 + 1, tl, tm, l, r);
- node right = get(v * 2 + 2, tm + 1, tr, l, r);
- if(left.mx > right.mx) {
- return left;
- }
- else {
- return right;
- }
- }
- void update(int v, int tl, int tr, int pos, int val) {
- if(tl > pos || tr < pos) {
- return;
- }
- if(tl == tr) {
- t[v] = {val, n - val};
- return;
- }
- int tm = (tl + tr) >> 1;
- update(v * 2 + 1, tl, tm, pos, val);
- update(v * 2 + 2, tm + 1, tr, pos, val);
- if(t[v * 2 + 1].mx > t[v * 2 + 2].mx) {
- t[v] = t[v * 2 + 1];
- }
- else {
- t[v] = t[v * 2 + 2];
- }
- }
- int f_get(vector<int> &t, int pos) {
- int sum = 0;
- if(pos >= t.size()) {
- return f_get(t, t.size() - 1);
- }
- while(pos > 0) {
- sum += t[pos];
- pos -= (pos & (-pos));
- }
- return sum;
- }
- void f_update(vector<int> &t, int pos, int val) {
- while(pos < t.size()) {
- t[pos] += val;
- pos += (pos & (-pos));
- }
- }
- signed main() {
- seriy();
- cin >> n >> q >> k;
- vector<int> a(n);
- vector<pair<int, int>> lol(n);
- for(int i = 0; i < n; i++) {
- cin >> a[i];
- lol[i] = {a[i], a[i]};
- }
- vector<int> b = a;
- b.push_back(INF);
- b.push_back(-INF);
- sort(all(b));
- vector<rq> close(n, {-INF, INF});
- for(int i = n - 1; i >= 0; i--) {
- int pos = lower_bound(all(b), a[i]) - b.begin();
- int pos3 = upper_bound(all(b), lol[i].y + k) - b.begin() - 1;
- close[i].r = get(0, 0, b.size() - 1, pos, pos3).pos;
- update(0, 0, b.size() - 1, pos, cur);
- cur++;
- }
- cur = 0;
- fill(all(t), node{-INF, INF});
- for(int i = 0; i < n; i++) {
- int pos = lower_bound(all(b), a[i]) - b.begin();
- int pos3 = upper_bound(all(b), lol[i].y + k) - b.begin() - 1;
- close[i].l = get(0, 0, b.size() - 1, pos, pos3).mx;
- if(close[i].l == INF) close[i].l = -INF;
- close[i].num = i;
- update(0, 0, b.size() - 1, pos, cur);
- cur++;
- }
- vector<rq> req(q);
- vector<vector<pair<int, int>>> rr(n);
- for(int j = 0; j < q; j++) {
- int l, r;
- cin >> l >> r;
- l--;
- r--;
- rr[r].push_back({l, j});
- req[j] = {l, r, j};
- }
- for(int i = 0; i < n; i++) {
- sort(all(rr[i]), greater<pair<int, int>>());
- }
- vector<rq> close2 = close;
- vector<rq> close3 = close;
- sort(all(close2), [&](rq a, rq b) {
- return a.r < b.r || a.r == b.r && a.l > b.l;
- });
- sort(all(close3), [&](rq a, rq b) {
- return a.l > b.l || a.l == b.l && a.r < b.r;
- });
- // for(auto i : close3) {
- // cerr << i.l << " " << i.r << " " << i.num << '\n';
- // }
- // cerr << '\n';
- vector<int> res(q);
- vector<int> inside(MAXN);
- vector<int> right(MAXN), left(MAXN);
- int cur_r = 0, cur_l = 0, was = 0;
- sort(all(req), [&](rq a, rq b) {
- return a.l > b.l || a.l == b.l && a.r < b.r;
- });
- vector<int> kek_right(q);
- for(auto i : req) {
- while(cur_l < close3.size() && close3[cur_l].l >= i.l) {
- f_update(right, close3[cur_l].num + 1, 1);
- cur_l++;
- }
- // int cnt1 = 0;
- // for(int p = i.l; p <= i.r; p++) {
- // if(close[p].l >= i.l) cnt1++;
- // }
- // cerr << cur_l << " " << (f_get(right, right.size() - 1) - f_get(right, i.r + 1)) << '\n';
- int lol_right = cur_l - (f_get(right, right.size() - 1) - f_get(right, i.r + 1));
- // cerr << i.l << " " << i.r << " " << cnt1 << " " << lol_right << '\n';
- kek_right[i.num] = lol_right;
- }
- for(int i = 0; i < n; i++) {
- for(auto j : rr[i]) {
- int r = i;
- int l = j.x;
- int num = j.y;
- int cnt1 = 0, cnt_inf = 0;
- while(cur_r < close2.size() && close2[cur_r].r <= r) {
- // cerr << close[cur_r].l + 1 << " ";
- f_update(left, close2[cur_r].num + 1, 1);
- f_update(inside, close2[cur_r].l + 1, 1);
- cur_r++;
- }
- // // cerr << '\n';
- int in = f_get(inside, r + 1) - f_get(inside, l);
- int kek_left = cur_r - f_get(left, l);
- // cerr << cur_l << '\n';
- // cerr << l << " " << r << " ";
- res[num] -= in;
- res[num] += kek_left;
- res[num] += kek_right[num];
- for(int p = l; p <= r; p++) {
- if(close[p].l >= l) cnt1++;
- }
- // assert(cnt1 == kek_left);
- // cerr << cnt1 << " " << kek_right[num] << '\n';
- res[num] = r - l + 1 - res[num];
- }
- }
- for(auto i : res) {
- cout << i << " ";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment