1012 数星星 Stars 树状数组 值域线段树
链接:https://ac.nowcoder.com/acm/contest/26896/1012
来源:牛客网
题目描述
天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。如果一个星星的左下方(包含正左和正下)有k颗星星,就说这颗星星是k级的。
例如,上图中星星5是3级的(1,2,4在它左下),星星2,4是1级的。例图中有1个0级,2个1级,1个2级,1个3级的星星。
给定星星的位置,输出各级星星的数目。一句话题意 \ 给定n个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。
输入描述:
第一行一个整数N,表示星星的数目;
接下来N行给出每颗星星的坐标,坐标用两个整数x,y表示;
不会有星星重叠。星星按y坐标增序给出,y坐标相同的按x坐标增序给出。
输出描述:
N行,每行一个整数,分别是0级,1级,2级,……,N-1级的星星的数目。
备注:
对于全部数据,1≤N≤1.5×104,0≤x,y≤3.2×1041 \le N \le1.5 \times 10^4,0 \le x,y \le 3.2 \times10^41≤N≤1.5×104,0≤x,y≤3.2×104。
分析
树状数组和线段树都可以写,不过 由于x 是从0开始的,线段树做法的话,要么让x 从1 开始,要么把树的范围变成(0到N)。。树的范围一开始尽可能大一点。。。不知道为啥写wa 了, 可能少写了了一位
值域线段树:查询任意区间内元素出现过多少次
#include<bits/stdc++.h> #define bd cout<<"debug"<<endl; #define ul (u<<1) #define ur (u<<1|1) using namespace std; #define int long long const int N = 1e5+10; int sum[N]; struct node { int l,r,v; } tr[N * 4]; void pu(int u) { tr[u].v=tr[ul].v+tr[ur].v; } void build(int u,int l,int r) { tr[u] = {l,r,0}; if(l == r) return;int mid = l + r >> 1; build(ul,l,mid);build(ur,mid+1,r); } void up(int u,int x) { if(tr[u].l==x&&tr[u].r==x) { tr[u].v++;return ; } if(x<=(tr[u].l+tr[u].r>>1))up(ul,x); if(x>(tr[u].l+tr[u].r>>1))up(ur,x); pu(u); } int query(int u,int l,int r) { if( l <= tr[u].l && tr[u].r <= r) { return tr[u].v; } int mid = tr[u].l + tr[u].r >> 1,sum = 0; if(l <= mid ) sum += query(u<<1,l,r); if(mid < r) sum += query(u<<1|1,l,r); return sum; } signed main() { int n; cin>>n; build(1,1,N-3); for(int i = 1;i <= n;i ++ ) { int x,y;cin>>x>>y;x ++ ; sum[query(1,1,x)] ++ ; up(1,x); } for(int i = 0;i<=n - 1;i ++ ) { cout<<sum[i]<<'\n'; } }

浙公网安备 33010602011771号