CF1404C Fixed Point Removal 题解

题面

初看题有点不好下手。

考虑把数字变成 (i-a_i),这样操作就变成了删掉一个 (0)、之后的数 (-1)

显然如果一个数 (<0) 那么它一定不能被删除,可以直接忽略。

可以发现一个数可以被删掉,当且仅当它前面能被删掉的数的个数 (le i-a_i)。因为先删后面不会影响前面。

考虑把询问离线,按右端点排序,从左到右扫过去。维护一个序列 ({f_i}) 表示 (isim) 结尾能删多少个数。由定义可知 (f) 序列是单调不升的。于是可以二分一个最大的 (f_j) 满足 (f_jge i-a_i),把 ([1,j])(f) 全部 (+1)。直接二分 + 树状数组做。

#include <bits/stdc++.h>
#define DC int T = gi <int> (); while (T--)
#define DEBUG fprintf(stderr, "Passing [%s] line %d
", __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
", ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/xsl19/p/cf1404c.html