【题解】CF91B

传送门


题目大意:

  • 给定 \(n\) 个正整数 。

  • 对于每一个数 \(a_i\),需要输出一个答案:

    • \(a_j > a_i\)\(j > i\)
    • 在满足第一条的基础上使 \(j-i-1\) 尽可能大,此时 \(j-i-1\) 即为答案。
    • 若没有找到 \(j\) 使得 \(a_j > a_i\)\(j > i\),输出 \(-1\)

本题思路

\(a_j > a_i\)\(j > i\) 可以想到逆序对,既然刚学了值域线段树,那就用值域线段树吧。

不会值域线段树的先做这题

但注意数据范围:\(a_i \le 10^9\),直接开数组会爆,故需离散化一下。

离散化很简单,举个例子:

\(1\quad-100\quad5\quad-10^9\)

离散化大概就是:如果一个数 \(i\) 是数组中第 \(j\) 大(或小)的,那么就用 \(j\) 来代替 \(i\)

上面的数组离散化就变成了(从大到小)

\(2\quad3\quad1\quad4\)

本题另一个需要注意的地方是:答案求的是最大值,所以线段树保存的是最大值。


\(\color{black}\texttt{AC}\) \(\color{black}\texttt{CODE}\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#define lpos pos << 1
#define rpos pos << 1 | 1
using namespace std;

const int MAXN = 1e5 + 5;

int n;
int ans[MAXN];

struct num
{
	int val, id;
	bool operator <(const num &x)const
	{
		if (x.val == val)
		{
			return x.id > id;
		}
		return x.val > val;
	}
}a[MAXN];

struct tree
{
	int l, r, val;
}t[MAXN << 2];

void pushup(int pos)
{
	t[pos].val = max(t[lpos].val, t[rpos].val);
}

inline void build(int pos, int l, int r)
{
	t[pos].l = l, t[pos].r = r;
	if (l == r)
	{
		return;
	}
	int mid = (l + r) >> 1;
	build(lpos, l, mid);
	build(rpos, mid + 1, r);
}

inline void update(int pos, int dis)
{
	int l = t[pos].l, r = t[pos].r;
	if (l == r)
	{
		t[pos].val = dis;
		return;
	}
	int mid = (l + r) >> 1;
	if (dis <= mid)
	{
		update(lpos, dis);
	}
	else
	{
		update(rpos, dis);
	}
	pushup(pos);
}

inline int query(int pos, int L, int R)
{
	int l = t[pos].l, r = t[pos].r;
	if (l >= L && r <= R)
	{
		return t[pos].val;
	}
	int mid = (l + r) >> 1, res = -1;
	if (L <= mid)
	{
		res = query(lpos, L, R);
	}
	if (R > mid)
	{
		res = max(res, query(rpos, L, R));
	}
	return res;
}

int main()
{
	scanf("%d", &n);
	build(1, 1, n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i].val);
		a[i].id = i;
	}
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; i++)
	{
		int id = a[i].id;
		update(1, id);
		int res = query(1, 1, n);
		if (res >= 0)
		{
			ans[id] = res - id - 1;
		}
		else
		{
			ans[id] = -1;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		printf("%d ", ans[i]);
	}
	return 0;
}
posted @ 2021-08-07 17:45  mango09  阅读(36)  评论(0编辑  收藏  举报
-->