POJ 2352 Stars (扫描线+树状数组)

Description:

平面内给出n个点的坐标,定义一个点的阶数为平面内横纵坐标都严格小于该点的点的数量(也就是平面内在该点的左下角的点数),问平面内的点的阶数都为多少.

Input:

n及n格点坐标

Output:

依次输出阶数为0到n-1的点的个数.

Analysis:

首先很明显用O(n^2)的暴力方式是要超时的,其实这题和上题求平面内矩形覆盖面积很像,我们不妨先把横坐标排好序,然后依次从前往后扫,只要同时维护在纵坐标数值区间内的点的个数就行,这里是单点修改,所以用树状数组就行啦。当然还要对纵坐标做个离散化,减少不必要的计算。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<time.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 0xffffff0;
const int MOD = 1e9 + 7;
const int maxn = 15005;

int n;
pair<int,int>  a[maxn];
int cnt[maxn];
int y[maxn],yc,id[32005];
int C[maxn];

void add(int x,int val){
    while(x<=yc){
        C[x]+=val;
        x+=x&-x;
    }
}
int sum(int x){
    int ans=0;
    while(x>0){
        ans+=C[x];
        x-=x&-x;
    }
    return ans;
}
int main() {

	int n;scanf("%d",&n);
	memset(cnt,0,sizeof(cnt));
	memset(C,0,sizeof(C));
	yc=0;
	_for(i,0,n){
        scanf("%d%d",&a[i].first,&a[i].second);
        y[++yc]=a[i].second;
	}
	sort(a,a+n);
	sort(y+1,y+yc+1);
	yc=unique(y+1,y+yc+1)-(y+1);
	for(int i=1;i<=yc;++i) id[y[i]]=i;
    for(int i=0;i<n;++i){
        pair<int,int> &now=a[i];
        int idx=id[now.second];
        int x=sum(idx);
        cnt[x]++;
        add(idx,1);
    }
    _for(i,0,n){
        printf("%d\n",cnt[i]);
    }

	return 0;
}

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/81560753