poj2352 starts 树状数组
有n个星星,按照y坐标的升序给出n个星星的坐标,
对于每一个星星,其level为在其左下方(包括正左,正下)的星星个数,输出n行,第i行代表等级为i个星星的星星的个数。
树状数组的插点问段
思路:
a[i] 存储星星的x坐标,
b[i] 表示0到i中x,y坐标小于i的个数,即i的等级
则对于每个b[i], 做一次扫描
ans[i] 表示等级为i的个数
则ans[b[i]]++;
明显,这样肯定tle。
所以要采用树状数组 。
a[i] 表示目前的星星中x坐标为i的个数
c[i] 为a[i]的树状数组
sum[i]表示坐标为1到i的个数的和,即为等级。
ans[i] 表示等级为i的个数。
4个数组,实际上只需要维护2个,c[i]和ans[i]。
注意一,这道题的输入,x和y是可以为0的,所以x统一加一,不然很麻烦。
注意二:这道题的启示,对于2维的,有时候可以对其中1维排序,转化成1维的来解决。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int MAXN=32000+10; 6 int c[MAXN]; 7 int ans[MAXN]; 8 int lowbit(int x) 9 { 10 return x&(-x); 11 } 12 void update(int x,int add) 13 { 14 while(x<=MAXN){ 15 c[x]+=add; 16 x+=lowbit(x); 17 } 18 } 19 int sum(int x) 20 { 21 int temp=0; 22 while(x>0){ 23 temp+=c[x]; 24 x-=lowbit(x); 25 } 26 return temp; 27 } 28 int main() 29 { 30 int n; 31 while(scanf("%d",&n)!=EOF){ 32 memset(ans,0,sizeof(ans)); 33 memset(c,0,sizeof(c)); 34 int i,j; 35 for(int t=0;t<n;t++){ 36 scanf("%d%d",&i,&j); 37 i++; 38 ans[sum(i)]++; 39 update(i,1); 40 } 41 for(int i=0;i<n;i++) 42 printf("%d\n",ans[i]); 43 } 44 return 0; 45 }