URAL_1028
将点排序后依次插入线段树,就可以将计算星星等级转化成区间求和的问题了,于是用线段树支持单点修改和区间求和即可。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXD 15010 #define MAXX 32010 struct Point { int x, y; }p[MAXD]; const int D = 32000; int N, num[4 * MAXX], h[MAXD]; int cmp(const void *_p, const void *_q) { Point *p = (Point *)_p, *q = (Point *)_q; if(p->y == q->y) return p->x < q->x ? -1 : 1; return p->y < q->y ? -1 : 1; } void init() { int i, j, k; for(i = 0; i < N; i ++) scanf("%d%d", &p[i].x, &p[i].y); qsort(p, N, sizeof(p[0]), cmp); memset(num, 0, sizeof(num)); } void update(int cur) { num[cur] = num[cur << 1] + num[(cur << 1) | 1]; } int Search(int cur, int x, int y, int s, int t) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x >= s && y <= t) return num[cur]; if(mid >= t) return Search(ls, x, mid, s, t); else if(mid + 1 <= s) return Search(rs, mid + 1, y, s, t); else return Search(ls, x, mid, s, t) + Search(rs, mid + 1, y, s, t); } void refresh(int cur, int x, int y, int k) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x == y) { ++ num[cur]; return ; } if(k <= mid) refresh(ls, x, mid, k); else refresh(rs, mid + 1, y, k); update(cur); } void solve() { int i, j, k; memset(h, 0, sizeof(h)); for(i = 0; i < N; i ++) { k = Search(1, 0, D, 0, p[i].x); ++ h[k]; refresh(1, 0, D, p[i].x); } for(i = 0; i < N; i ++) printf("%d\n", h[i]); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }