cdoj842-天下归晋 【树状数组】
http://acm.uestc.edu.cn/#/problem/show/842
天下归晋
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
晋朝统一天下已有十年,曹魏、孙吴、蜀汉这些曾与天下相争的王朝,都成为了过眼云烟,仅留于故事之中。
“爷爷,讲嘛讲嘛,再讲一次赤壁之战的故事嘛!”
“你个死小子,都讲多少遍了,还听!”
“就是想听打仗嘛!”
“你小子啊...行,我就再讲一次。当时曹公率领八十万大军欲渡长江,那船队规模才叫一壮观啊,长江都铺成陆地啰。当时是这样部署的....”
曹操的船队自西向东铺于长江之上,为了方便指挥,每艘船都被赋予了相应的等级。这个等级由该船西南方船只的数量决定,即不比该船靠东并且不比该船靠北的船的数目。那是一只多么庞大的船队啊,只惜周郎一把火,樯橹灰飞烟灭......
“太刺激了,打仗好好玩啊!爷爷你怎么那么清楚当时的事儿,你的腿就是赤壁时断的吗?”
通天的火光,被激流卷去的兄弟,无数的惨叫,折断后砸向自己左腿的船柱...
看了眼激动的孙子,老者咂咂嘴,淡淡说道:“爬山采药时摔的”。
Input
第一行,一个整数n表示曹军船只的数量。
接下来n行,每行一个对整数xi,yi。表示第i艘船的坐标。
数据保证不会有两艘船在同一位置。
1≤n≤100000,0≤xi,yi≤32000
Output
n行,每行1个整数,分别表示从0级到n−1级的船的数量。
行末不要有空格。
Sample input and output
Sample Input | Sample Output |
---|---|
5 1 1 5 1 7 1 3 3 5 5 |
1 2 1 1 0 |
思路:
树状数组可以解决,每条船的等级即统计每条船的左下方的船只数目。
将船只坐标由y从小到大排序,y坐标相同的根据x坐标从小到大排序。总之后面的点要保证在前面的点的右上方,这样插入时后面的船只不会影响到前面船只的等级,即前面船只的等级确定。
求和时sum(x)表示x坐标值小于等于x的船只个数
然后根据排序顺序将船只一个一个插入,求和,求出的和的那个等级的船只数加1,最后输出。
(注意树状数组c[]数组下标只能从1开始,所以所有坐标在处理时都加1)
代码:
1 #include <fstream> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstring> 6 #include <cmath> 7 #include <cstdlib> 8 9 using namespace std; 10 11 #define PI acos(-1.0) 12 #define EPS 1e-10 13 #define lll __int64 14 #define ll long long 15 #define INF 0x7fffffff 16 17 struct node{ 18 int x,y; 19 }point[100005]; 20 int n,tree[32005],cnt[100005]; 21 22 bool cmp(const node &r1,const node &r2); 23 int read(int pos); 24 void update(int pos,int val); 25 26 int main(){ 27 //freopen("D:\\input.in","r",stdin); 28 //freopen("D:\\output.out","w",stdout); 29 scanf("%d",&n); 30 for(int i=0;i<n;i++){ 31 scanf("%d %d",&point[i].x,&point[i].y); 32 } 33 sort(point,point+n,cmp); 34 for(int i=0;i<n;i++){ 35 cnt[read(point[i].x+1)]++; 36 update(point[i].x+1,1); 37 } 38 for(int i=0;i<n;i++) 39 printf("%d\n",cnt[i]); 40 return 0; 41 } 42 bool cmp(const node &r1,const node &r2){ 43 if(r1.y!=r2.y) return r1.y<r2.y; 44 else return r1.x<r2.x; 45 } 46 int read(int pos){ 47 int ans=0; 48 while(pos>0){ 49 ans+=tree[pos]; 50 pos-=pos&(-pos); 51 } 52 return ans; 53 } 54 void update(int pos,int val){ 55 while(pos<=32000){ 56 tree[pos]+=val; 57 pos+=pos&(-pos); 58 } 59 }