1012 数星星 Stars 树状数组 值域线段树

 链接:https://ac.nowcoder.com/acm/contest/26896/1012
来源:牛客网

题目描述

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。如果一个星星的左下方(包含正左和正下)有k颗星星,就说这颗星星是k级的。
stars1.png 
例如,上图中星星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

输入

复制
5
1 1
5 1
7 1
3 3
5 5

输出

复制
1
2
1
1
0

备注:

对于全部数据,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^41N1.5×104,0x,y3.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';
    }
}

 

posted @ 2022-08-08 19:25  er007  阅读(62)  评论(0)    收藏  举报