洛谷简单入门题-小鱼比可爱-线段树思路

洛谷简单入门题-小鱼比可爱-线段树练习思路

题目链接
这个题直接一直循环就能过,不过最近刚学过线段树,就练习一下,记录一下

#include 

#define INII 1, n, 1
#define DEFI int l, int r, int t
#define LSON l, (l + r) >> 1, t << 1
#define RSON ((l + r) >> 1) + 1, r, t << 1|1
#define SNUM 109

using namespace std;

int S[SNUM], T[SNUM << 2], N[SNUM];

void build(DEFI)
{
	//到达了子节点直接赋值
	if (l == r)
	{
		T[t] = S[l];
		S[l] = t;
		return ;
	}
	build(LSON);
	build(RSON);
	//将根节点的值赋为此节点所管理节点的最大值
	T[t] = max(T[t << 1], T[t << 1|1]);
	return ;
}

/*
 * 求解函数思路:
 * 第一个判断:
 * 如果不是根节点,但当前节点的值表示此节点所管理节点的最大值,所以如果此节点的值小于所求点的值,说明此节点下的所有节点的值都小于此节点的值,因此直接返回区间长度
 * 第二个判断:
 * 找到子节点必定是递归的结果,所以直接返回 0 或 1
 * 后两个判断:
 * 如果左边界在所求节点的左边,那就要查看所有左边的节点
 * 如果中间值在所求节点左边,说明右边还有数,因此也要往左找
 * */

int query(int n, int s, DEFI)
{
	if (n > T[t]) return r - l + 1;
	if (l == r) if (n > T[t]) return 1; else return 0;
	int e = 0, m = (l + r) >> 1;
	if (l < s) e += query(n, s, LSON);
	if (m < s) e += query(n, s, RSON);
	return e;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n;
	cin >> n;
	//S[i] 数组即用来储存刚开始输入的数
	//又用来储存按顺序的各个数在树中的位置
	for (int i = 1; i <= n; i++) cin >> S[i];
	//建树
	build(INII);
	for (int i = 1; i <= n; i++)
	{
		if (i != 1) cout << ' ';
		cout << query(T[S[i]], i, INII);
	}
	cout << endl;
	return 0;
}

你可能感兴趣的:(题解)