蓝桥杯 1265. 数星星 知识点:树状数组

49 阅读1分钟

1265. 数星星 - AcWing题库

视频解析:AcWing 1265. 数星星(每日一题)_哔哩哔哩_bilibili

思想

假设当前坐标是[x,y],那么题意就是求小于等于x的星星有多少个,下图中x就有4个星星,x自身的星星需要抛除掉。 image.png 那么这道题就转换为了求<=x的区间的星星的个数。

求某个区间个数可以转化为区间和,每个位置如果有星星就是1,没有就是0,最后对该区间求一个前缀和就求出了该区间的星星个数。

那么现在我们就有两个点需要计算:

1、求区间前缀和

2,修改区间内某个点的值(是星星就是1,不是就是0)

可以满足需求的数据结构有:树状数组,线段树,平衡树。

树状数组的常数比较小,所以优先树状数组。

code

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

int tr[M];  //树状数组初始化为0,表示每个点上都没有星星 
int level[M];

int lowbit(int x)
{
	return x&-x;
}

//查询从[0,x]的前缀和,即[0,x]的星星的个数
int query(int x)
{
    int res=0;
	for(int i=x;i;i-=lowbit(i))
	res+=tr[i];
return res;
}

//给区间内某个点加上v值 
void add(int x,int v)
{
	for(int i=x;i<M;i+=lowbit(i))
	tr[i]+=v; 
}
int main()
{
	int n;cin>>n;
	for(int i=0;i<n;i++)
	{
	  int x,y;cin>>x>>y;
	  		
	  x++;  //树状数组的下标从1开始
	  
	   int t=query(x);  //求一下[0,x]的前缀和,即<=x的星星个数 
       level[t]++;  //下一轮
	   add(x,1);  //给点x加上1,表示该位置上有星星 
	}
	
	for(int i=0;i<n;i++)cout<<level[i]<<endl; 
	return 0;
}

image.png