poj2481_树状数组
题意:FJ有n头牛(编号为1~n),每一头牛都有一个测验值[S, E],如果对于牛i和牛j来说,它们的测验值满足下面的条件则证明牛i比牛j强壮:Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮。
分析:将[s,e]看成是而为坐标轴的横纵坐标,画出各个点,我们发现答案就是每个点左上的点的个数。将e降序,再将s升序,就可以转化成一维。
例如:
1 2
1 2
0 3
3 4,排序后为
3 4
0 3
1 2
1 2,这样就转化成横坐标前面小于它的个数。
这个题离散到大于等于1的范围内即可。
难点是,对重复坐标的处理,之前做过的题都是不会有重复的。
重复的点直接拷贝答案就行,不用getsum().
代码:
View Code
1 #include <stdio.h> 2 #include <iostream> 3 #include <memory.h> 4 #include <algorithm> 5 using namespace std; 6 const int maxnum=100005; 7 struct node 8 { 9 int l,r; 10 int pos; 11 }array[maxnum]; 12 int tree[maxnum]; 13 int ans[maxnum]; 14 int n; 15 16 bool cmp(struct node a,struct node b) 17 { 18 if(a.r==b.r) 19 return a.l<b.l; 20 return a.r>b.r; 21 } 22 23 void update(int index,int add) 24 { 25 while(index<=maxnum) //因为没有紧凑化,所以<=maxn;如果紧凑化到n个散列号的话,<=n就可以了 26 { 27 tree[index]+=add; 28 index+=(-index)&index; 29 } 30 } 31 32 int getsum(int index) 33 { 34 int sum=0; 35 while(index>0) 36 { 37 sum+=tree[index]; 38 index-=(-index)&index; 39 } 40 return sum; 41 } 42 43 int main() 44 { 45 int i; 46 while(scanf("%d",&n) && n!=0) 47 { 48 for(i=0;i<n;i++) 49 { 50 scanf("%d%d",&array[i].l,&array[i].r); 51 array[i].pos=i; 52 } 53 sort(array,array+n,cmp); 54 memset(tree,0,sizeof(tree)); 55 int cnt=0; 56 for(i=0;i<n;i++) 57 { 58 if(i!=0 && array[i].l==array[i-1].l && array[i].r==array[i-1].r) 59 { 60 ans[array[i].pos]=ans[array[i-1].pos]; //注意 61 cnt++; 62 } 63 // else 这样为什么不行?????求助!!!! 64 // { 65 // update(array[i].l+1,1); 66 // ans[array[i].pos]=getsum(array[i].l+1)-1+cnt; 67 // } 68 else 69 ans[array[i].pos]=getsum(array[i].l+1); 70 update(array[i].l+1,1); 71 } 72 for(i=0;i<n-1;i++) 73 printf("%d ",ans[i]); 74 printf("%d\n",ans[i]); 75 } 76 return 0; 77 } 78 79 /* 80 4 81 1 2 82 1 2 83 0 3 84 3 4 85 */