因为输入的 Y 是非递减序列,所以只用考虑输入的 X 值,当输入<x,y>时,该点的level即是在该点之前已经输入了多少个 x 坐标比当前小的星
星数。所以我们要记录的是任何 x 坐标之前已经出现了多少个星星。对于动态区间问题,线段树是利器!
#include <iostream> using namespace std; typedef unsigned short unshort; const unshort MAX_N = 32000; unshort N; unshort ans[15005]; struct Node { unshort left; unshort right; unshort level; } tree[MAX_N*3]; void createTree(int root, unshort l, unshort r) { tree[root].left = l; tree[root].right = r; tree[root].level = 0; if(l == r) return; int mid = tree[root].left + tree[root].right >> 1; if(r <= mid) { createTree(root<<1, l, r); return; } if(l > mid) { createTree((root<<1)+1, l, r); return; } createTree(root<<1, l, mid); createTree((root<<1)+1, mid+1, r); } //插入坐标点<x,->,计算该点前已存在多少层数,并跟新区间 unshort search(unshort x, int root) { if(x == tree[root].right) { for(int i=root; i>=1; i>>=1)//更新区间 tree[i].level++; return tree[root].level - 1; } unshort mid = (tree[root].left + tree[root].right)>>1; if(x<=mid) return search(x, root<<1); else return search(x, (root<<1)+1)+tree[root<<1].level; //注意当向右子树搜索时,要加上左子树已经有了的层数 } int main() { unshort x, y; while(~scanf("%hu", &N)) { memset(ans, 0, sizeof(ans)); createTree(1, 1, MAX_N); for(int i=0; i<N; i++) { scanf("%hu%hu", &x, &y); ans[search(x,1)]++; } for(int i=0; i<N; i++) printf("%hu/n", ans[i]); } return 0; }
