标签:
#include <stdio.h>
#include <string>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define MAX 32000
int num[MAX+100];
int lowbit(int x)
{
return x&(-x);
}
void modify(int x)
{
for(int i=x; i<32010; i+=lowbit(i))
num[i]++;
}
int sum(int x)
{
int all =0;
for(int i=x; i>0; i-=lowbit(i))
all += num[i];
return all;
}
int level[MAX+100];
int main()
{
//freopen("read.txt", "r", stdin);
int n;
while(~scanf("%d", &n) )
{
memset(level, 0, sizeof(level));
memset(num, 0, sizeof(num) ); //初始化问题重要
int x, y;
for(int i=0; i<n; i++)
{
scanf("%d%d", &x, &y);
level[sum(x+1)]++;
modify(x+1);
}
for(int i=0; i<n; i++)
printf("%d\n", level[i]);
}
}
/*
题目意思就是说,给你一张star maps,每个star有自己的level,level是这样计算的:(Let the level of a star be an amount of the stars that are not higher and not to the right of the given star.)统计这个star左下角star的个数,就是这个star的level。现在要你总计图中level从0到N-1的star分别有多少个?
题目输入描述中明确告诉我们,输入的坐标是按Y的升序、如果Y相等,则按X的升序。所以我们发现我们可以完全忽略Y,只要统计小于本身X的star个数,就是level了。现在我们用一个数组a[]统计X坐标为i的个数(增加一个既a[i]++;);同时对每个star计算的得level。
这样对于X坐标为j的star,他得level为:
level=a[0]+a[1]+a[2]+…+a[j]
如果这样计算的话,每个level最坏时间要用O(m),计算n-1个level,这样要用O(mn)的时间复杂度,对于这题的数据而言,这无疑是无法接受的。我们发现,对于计算level,这是个查询区间问题sum[0,j], 如果没有元素的变更(既数组a是不变的),我们完全可以存储sum[0,k](k=0,2,……),然后对任意给定的查找区间[i,j],都可以方便的用ans=sum[1,j]-sum[1,i-1],当然这只是没有元素改变的情况下的比较优化的解法.那么对于有元素变更的问题是否有更高效的方法呢?这让我们想到的树状数组。
树状数组所针对问题:已知数组a[],元素个数为n,现在更改a中的元素,要求得新的a数组中i到j区间内的和(1<=i<=j<=n).
这题是比较简单和明显的树状数组,我们先不讨论如何实现树状数组。只告诉你树状数组现在有2个操作:
(1) add(int i,int val) //将第i个元素更改val
(2) sum(int i) //求前i项和
所以这题我们的伪代码可以如下实现:
for(i=0;i<n;i++)
{
1. sacnf(x,y);
2. cnt[sum(x+1)]++;
3. add(x+1,1);
4.
}
5.print:cnt[0,n-1];
上面因为树状数组是从1开始计数的,而坐标有可能为0,所以我们统一都加1;sum(x+1)就是计算当前star的level值,所以当前level个数加1;add(x+1,1)操作表示对当前元素更改(既+1);最后打印cnt数组。
树状数组的实现及其思想
那么树状数组是如何实现快速对数组更新和区间求和的呢?
关于树状数组的实现和思想,这个再不细说,参考下面资料:
http://baike.baidu.com/view/1420784.htm
http://www.cnblogs.com/yykkciwei/archive/2009/05/08/1452889.html
*/
标签:
原文地址:http://www.cnblogs.com/sober-reflection/p/f9ca7bf4b860062d157757b8fcd835f8.html