1 条题解
-
0
题意分析
本题要求我们计算每个恒星的等级,其中等级定义为满足以下条件的恒星数量:
- 该恒星的坐标不大于当前恒星的坐标
- 该恒星的坐标不大于当前恒星的坐标
由于题目保证输入数据已按坐标升序排列,相同时按升序排列,因此我们可以简化计算过程。对于第个恒星,其等级等于之前所有坐标不超过当前的恒星数量。
解题思路
关键观察
- 输入顺序特性:由于恒星已按升序排列,处理到第颗恒星时,只需要考虑前面所有恒星的坐标是否小于等于当前即可
- 高效查询:需要一种数据结构,能够高效地:
- 查询坐标小于等于当前的恒星数量
- 插入新的坐标
解决方案
使用树状数组(Fenwick Tree)或线段树来维护坐标的前缀和:
- 初始化一个足够大的树状数组(考虑到坐标最大为)
- 按输入顺序处理每个恒星:
- 查询当前坐标的前缀和,即为该恒星的等级
- 更新等级计数数组
- 将当前坐标插入树状数组
算法选择
选择树状数组的原因:
- 时间复杂度为,其中是坐标的最大值()
- 空间复杂度为
- 实现简单高效,适合本题数据规模
代码实现
#include<cstdio> #include<cstring> #define mid ((left+right)>>1) #define lson rt<<1,left,mid #define rson rt<<1|1,mid+1,right using namespace std; const int MAXN = 32005; int sum[MAXN<<2],level[MAXN<<2]; void update(int rt,int left,int right,int data){ ++sum[rt]; if(left==right) return; if(data <= mid) update(lson,data); else update(rson,data); } int query(int rt,int left,int right,int l,int r){ if(left==l && right==r) { return sum[rt]; } int m = mid; if(r <= m) return query(lson,l,r); else if(l > m) return query(rson,l,r); else return query(lson,l,m)+query(rson,m+1,r); } int main(){ int n,x,y; while(~scanf("%d",&n)){ memset(sum, 0, sizeof(sum)); memset(level, 0, sizeof(level)); for(int i=0; i<n; ++i){ scanf("%d%d",&x,&y); ++x; ++level[query(1,1,MAXN,1,x)]; update(1,1,MAXN,x); } for(int i=0; i<n; ++i) printf("%d\n",level[i]); } return 0; }
- 1
信息
- ID
- 1353
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者