题目:http://poj.org/problem?id=2352 题意:平面上有n个星星,每个星星的等级是比该星星的X和Y坐标都小的星星的个数,给出每个星星的坐标(按y轴升序),输出等级0~n-1每个等级的星星个数。 思路:线段树,因为y轴升序给出,我们只考虑x轴就可以, 每次查询只需要查询0~x区间的个数即可。#include <stdio.h> #include <string.h> const int maxn=32000; struct SegMentTree { int l, r, sum; }st[maxn<<2]; int lvl[maxn+10]; int n, x, y; void BuildTree(int left, int right, int v) { st[v].l=left, st[v].r=right; if (left==right) { st[v].sum=0; return; } int lc=v<<1; int rc=lc+1; int mid=(left+right)>>1; BuildTree(left, mid, lc); BuildTree(mid+1, right, rc); st[v].sum=st[lc].sum+st[rc].sum; } void Insert(int left, int right, int v) { if (st[v].l==left&&st[v].r==right) { st[v].sum++; return; } int lc=v<<1; int rc=lc+1; int mid=(st[v].l+st[v].r)>>1; if (mid>=right) Insert(left, right, lc); else if (left>mid) Insert(left, right, rc); else { Insert(left, mid, lc); Insert(mid+1, right, rc); } st[v].sum=st[lc].sum+st[rc].sum; } int Query(int left, int right, int v) { if (st[v].l==left&&st[v].r==right) return st[v].sum; int lc=v<<1; int rc=lc+1; int mid=(st[v].l+st[v].r)>>1; if (mid>=right) return Query(left, right, lc); else if (left>mid) return Query(left, right, rc); else return Query(left, mid, lc)+Query(mid+1, right, rc); } int main() { //freopen("in.txt", "r", stdin); while (scanf("%d", &n)==1) { memset(lvl, 0, sizeof(lvl)); BuildTree(0, maxn, 1); for (int i=0; i<n; i++) { scanf("%d %d", &x, &y); lvl[Query(0, x, 1)]++; Insert(x, x, 1); } for (int i=0; i<n; i++) printf("%d\n", lvl[i]); } }