标签:
http://poj.org/problem?id=2352
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 37696 | Accepted: 16419 |
Description

Input
Output
Sample Input
5 1 1 5 1 7 1 3 3 5 5
Sample Output
1 2 1 1 0
Hint
Source
思路:树状数组
分析:
1 题目是要求出每一个点的左下(正左+正下)有几个星星,那个这个点就是第几层,最后输出0~n-1层的点的个数。比如样列编号为5的星星,左下有3个星星那么5就处于第三层
2 利用树状数组,我们知道树状数组C中,C[i]表示的是原先数组A中的某一段和。题目明确指出输入的时候是按照y值增大的顺序(y相同是x增大),那么我们应该要用什么做为原先的数组A呢,很显然就是X轴,就是A[2]表示x = 2的点的个数。那么当新加入一个点的x值为2的时候,A[2]++,这个时候就是要更新C[2],C[2+lowbit(2)]...
3 那怎么求某个点的左下有几个星星呢,很显然处在左下的点的x值肯定小于等于当前点的,那么就是相当与树状数组求和,那么整道题的思路就完成
4 注意更新树状数组的时候,注意x<=MAXN,不是输入的n。因为更改了A[x],就要更新C[x] , C[x+lowbit(x)]...
5 题目输入的x的坐标可能为0,所以这边我们把所有的x+1,这就避免了TLE
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 32010;
int n , ans[MAXN];
int treeNum[MAXN];
int lowbit(int x){
return x&(-x);
}
int getSum(int x){
int sum = 0;
while(x){
sum += treeNum[x];
x -= lowbit(x);
}
return sum;
}
void add(int x , int val){
while(x < MAXN){
treeNum[x] += val;
x += lowbit(x);
}
}
int main(){
int x , y;
while(scanf("%d" , &n) != EOF){
memset(treeNum , 0 , sizeof(treeNum));
memset(ans , 0 , sizeof(ans));
for(int i = 0 ; i < n ; i++){
scanf("%d%d" , &x , &y);
x++;
ans[getSum(x)]++;
add(x , 1);
}
for(int i = 0 ; i < n ; i++)
printf("%d\n" , ans[i]);
}
return 0;
}
思路:线段树+单点更新#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 32010
struct Node{
int left;
int right;
int sum;
};
Node node[4*MAXN];
int vis[MAXN];
/*建立一颗线段树*/
void buildTree(int left , int right , int pos){
node[pos].left = left;
node[pos].right = right;
node[pos].sum = 0;
if(left == right)
return;
int mid = (left+right)>>1;
buildTree(left , mid , pos<<1);
buildTree(mid+1 , right , (pos<<1)+1);
}
/*单点更新*/
void update(int index , int pos){
if(node[pos].left == node[pos].right){
node[pos].sum++;
return;
}
int mid = (node[pos].left+node[pos].right)>>1;
if(index <= mid)
update(index , pos<<1);
else
update(index , (pos<<1)+1);
node[pos].sum = node[pos<<1].sum + node[(pos<<1)+1].sum;
}
/*区间查询*/
int query(int left , int right , int pos){
if(node[pos].left == left && node[pos].right == right)
return node[pos].sum;
int mid = (node[pos].left+node[pos].right)>>1;
if(right <= mid)
return query(left , right , pos<<1);
else if(left > mid)
return query(left , right , (pos<<1)+1);
else
return query(left , mid , pos<<1)+query(mid+1 , right , (pos<<1)+1);
}
int main(){
int Case , n;
int x , y;
scanf("%d" , &Case);
n = Case;
buildTree(0 , MAXN , 1);
memset(vis , 0 , sizeof(vis));
while(Case--){
scanf("%d%d" , &x , &y);
vis[query(0 , x , 1)]++;
update(x , 1);
}
for(int i = 0 ; i < n ; i++)
printf("%d\n" , vis[i]);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
求左下角星星之和 树状数组或线段树 poj 2352 Stars
标签:
原文地址:http://blog.csdn.net/acm_10000h/article/details/48030033