这是一道可以用线段树做的题目,题目大意是计算某一刻星星坐标左下方的星星数(自己没有被包括),很明显的线段树,由于输入数据已经保证y坐标是按照递增顺序输出的,那么可以对每一个y,将其x打成一棵线段树,然后依次找出[0,x[i]]之间的cover值就可以了,要注意一下是先计算当前x[i]的cover值后在将x插入线段树。因为自己这个点不被计算到星星等级中。。。这题用树状数组空间时间都要省很多。。。
#include <iostream>
using namespace std;
const int size = 15000;
struct STree
{
int l, r;
int cover;
}stree[6*size+10];
void creat(int num, int l, int r)
{
stree[num].l = l, stree[num].r = r, stree[num].cover = 0;
if (l == r) return ;
int mid = (l+r)>>1;
int p = num << 1;
creat(p, l, mid);
creat(p+1, mid+1, r);
}
void insert(int num, int l, int r)
{
int a = stree[num].l, b = stree[num].r;
int mid = (a+b) >> 1;
int p = num << 1;
if (l == a && r == b){
stree[num].cover ++;
return ;
}
if (r <= mid){
insert(p, l, r);
}
else
if (l > mid)insert(p+1, l, r);
else {
insert(p, l, mid);
insert(p+1, mid+1, r);
}
stree[num].cover = stree[p].cover + stree[p+1].cover;
}
int find1(int num, int l, int r)
{
int a = stree[num].l, b = stree[num].r;
int mid = (a+b) >> 1;
int p = num << 1;
int ll = 0, rr = 0;
if (l <= a && r >= b){
return stree[num].cover;
}
if (r <= mid)ll= find1(p, l, r);
else
if (l > mid)rr= find1(p+1, l, r);
else {
ll = find1(p, l, mid);
rr = find1(p+1, mid+1, r);
}
return ll+rr;
}
int ligh[size+10];
int n;
int x[size+10], y;
int main()
{
while (scanf("%d", &n) != EOF){
int left = INT_MAX, right = INT_MIN;
for (int i = 0; i < n; i ++){
scanf("%d%d", &x[i], &y);
if (x[i] < left)left = x[i];
if (x[i] > right)right = x[i];
}
creat(1, left, right);
for (int i = 0; i < n; i ++)ligh[i] = 0;
for (int i = 0; i < n; i ++){
ligh[find1(1, 0, x[i])] ++;//注意是先计算再插入
insert(1, x[i], x[i]);
}
for (int i = 0; i < n; i ++){
printf("%d\n", ligh[i]);
}
}
return 0;
}
树状数组版:
#include <iostream>
using namespace std;
const int size = 32010;
const int N = 15010;
int x;
int tree[size];
int ligh[N];
int lowbit(int x)
{
return x&(x^(x-1));
}
void insert(int k)
{
while (k <= size){
tree[k] ++;
k += lowbit(k);
}
}
int find1(int k)
{
int sum = 0;
while (k >= 1){
sum += tree[k];
k -= lowbit(k);
}
return sum;
}
int main()
{
int n, y;
while (scanf("%d", &n) != EOF){
for (int i = 0; i < n; i ++)ligh[i] = 0;
memset(tree, 0, sizeof(tree));
for (int i = 0; i < n; i ++){
scanf("%d%d", &x, &y);
ligh[find1(x+1)] ++;
insert(x+1);
}
for (int i = 0; i < n; i ++){
printf("%d\n", ligh[i]);
}
}
return 0;
}