1265. 数星星

树状数组应用的模板题,写此篇题解前我需要引用一下此位大佬的:https://www.acwing.com/solution/content/39139/
大佬的题解很好,但最醍醐灌顶的是大佬的总结:根据题目特性,确定初步解题思路,优先使用暴力,再去考虑优化
对于刷题,我一直没有什么较好的内化、学习思路,大佬所总结的收获正好是我此时此刻最需要的

接下来是正题:
对于此题,可以发现输入方式是从左下到右上,最值得深思是,这样的输入顺序,确定了之前输入的星星的级别,或者说,后续输入的星星的纵坐标必定大于等于之前输入的星星,如此,对于题目所求,我们就不必要考虑纵坐标了
只需要考虑在当前条件下,每个星星横坐标是否小于此个星星的横坐标,如此就是求前缀和,先考虑暴力做法:无需考虑纵坐标,即枚举每个星星,只需要判断之前放的星星的横坐标是否小于枚举的即可判断星星级数是否加一

#include <iostream>
using namespace std;
const int N = 15010;
int a[N], b[N], c[N];  //数组ab记录坐标,c[i]表示星级i的数量
int n;
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d%d", &a[i], &b[i]);//实际上b(y向量)没有用,
    for(int i = 1; i <= n; i ++)
    {
        int cnt = 0;
        for(int j = 1; j < i; j ++)
            if(a[j] <= a[i]) cnt ++;
        c[cnt] ++;
    }
    for(int i = 0; i < n; i ++) printf("%d\n", c[i]);
    return 0;
}

233,但是这样明显过不了全部数据
每次都需要O(N)的查询,效率过慢,还得需要树状数组满足logN的更新与查询操作

#include<bits/stdc++.h>
using namespace std;
const int N=32010;

int n;
int level[N];
int tr[N];

//树状数组三大核心函数
int lowbit(int x)
{
    return x&-x;
}

int add(int x,int v)
{
    for(int i=x;i<=N;i+=lowbit(i)) tr[i]+=v;
}

int qurry(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i)) 
        res+=tr[i];
    return res ;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x++;//全体星星坐标向右偏移一个单位,因为树状数组是从1开始的
        level[qurry(x)]++;//级数自增
        add(x,1);//更新树状数组
    }
    for(int i=0;i<n;i++)printf("%d\n",level[i]);
}

 更多的也可以参考这篇:https://www.acwing.com/solution/content/99925/

posted @ 2022-10-17 23:06  风乐  阅读(44)  评论(0)    收藏  举报