CF1404C Fixed Point Removal 題解
阿新 • • 發佈:2021-11-09
思維題
全部 \(+1\)。直接二分 + 樹狀陣列做。
初看題有點不好下手。
考慮把數字變成 \(i-a_i\),這樣操作就變成了刪掉一個 \(0\)、之後的數 \(-1\)。
顯然如果一個數 \(<0\) 那麼它一定不能被刪除,可以直接忽略。
可以發現一個數可以被刪掉,當且僅當它前面能被刪掉的數的個數 \(\le i-a_i\)。因為先刪後面不會影響前面。
考慮把詢問離線,按右端點排序,從左到右掃過去。維護一個序列 \(\{f_i\}\) 表示 \(i\sim\) 結尾能刪多少個數。由定義可知 \(f\) 序列是單調不升的。於是可以二分一個最大的 \(f_j\) 滿足 \(f_j\ge i-a_i\),把 \([1,j]\) 的 \(f\)
#include <bits/stdc++.h> #define DC int T = gi <int> (); while (T--) #define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__) #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout) #define fi first #define se second #define pb push_back #define mp make_pair using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair <int, int> PII; typedef pair <LL, int> PLI; typedef pair <LL, LL> PLL; template <typename T> inline T gi() { T x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();} while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return f * x; } template <typename T> inline T abs(T x) {return x < 0 ? -x : x;} const int N = 300003, M = N << 1; int n, q, a[N]; struct Query {int l, r, id;} b[N]; vector <Query> l[N]; int ans[N]; struct BIT { int tr[N]; #define lowbit(i) (i & (-i)) void add(int u, int x) {for (int i = u; i <= n; i += lowbit(i)) tr[i] += x;} int query(int x) {int res = 0; for (int i = x; i; i -= lowbit(i)) res += tr[i]; return res;} int query(int l, int r) {return query(r) - query(l - 1);} } t; int main() { n = gi <int> (), q = gi <int> (); for (int i = 1; i <= n; i+=1) a[i] = gi <int> (); for (int i = 1; i <= q; i+=1) b[i].id = i, b[i].l = gi <int> () + 1, b[i].r = n - gi <int> (), l[b[i].r].pb(b[i]); for (int i = 1; i <= n; i+=1) { if (a[i] <= i) { int l = 1, r = i, res = -1; while (l <= r) { int mid = (l + r) >> 1; if (t.query(mid) >= i - a[i]) res = mid, l = mid + 1; else r = mid - 1; } if (res != -1) t.add(1, 1), t.add(res + 1, -1); } for (auto x : l[i]) ans[x.id] = t.query(x.l); } for (int i = 1; i <= q; i+=1) printf("%d\n", ans[i]); return 0; }