洛谷简单入门题-小鱼比可爱-线段树练习思路
题目链接
这个题直接一直循环就能过,不过最近刚学过线段树,就练习一下,记录一下
#include <iostream>
#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;
}