题意:求坐标0到x间的点的个数
思路:线段树,主要是转化,根据题意的输入顺序,保证了等级的升序,可以直接求出和即当前等级的点的个数,然后在把这个点加入即可。
注意:线段树下标从1开始,所以把所有的x加1存储。
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define MAXN 32005 #define MAXL 15005 int ans; int lev[MAXL]; struct node{ int left,right,sum; int mid(){ return (left+right)>>1; } }tree[MAXN*4];//注意范围,4倍空间 void btree(int left,int right,int rt){//建树 tree[rt].left=left; tree[rt].right=right; if(left==right){ //scanf("%d",&tree[rt].sum); tree[rt].sum=0; return; } int mid=tree[rt].mid(); btree(left,mid,rt<<1); btree(mid+1,right,rt<<1|1); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间里的点数=左区间+右区间 } void query(int left,int right,int rt,int L,int R){//询问求和 if(L<=left&&right<=R){ ans+=tree[rt].sum; return; } int mid=tree[rt].mid(); if(R<=mid)query(left,mid,rt<<1,L,R);//区间在左子树 else if(L>mid)query(mid+1,right,rt<<1|1,L,R);//区间在右子树 else{ query(left,mid,rt<<1,L,R); query(mid+1,right,rt<<1|1,L,R); } } void update(int left,int right,int rt,int pos,int add){//单点更新函数 if(left==right){ tree[rt].sum+=add; return; } int mid=tree[rt].mid(); if(pos<=mid)update(left,mid,rt<<1,pos,add);//点在左子树 else update(mid+1,right,rt<<1|1,pos,add);//点在右子树 tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间和更新 } int main(){ int n,x,y,i; while(~scanf("%d",&n)){ btree(1,MAXN,1); memset(lev,0,sizeof(lev)); for(i=0;i<n;++i){ scanf("%d%d",&x,&y); ++x;//线段树从1开始 ans=0; query(1,MAXN-1,1,1,x); ++lev[ans];//先求和 update(1,MAXN-1,1,x,1);//后加1 } for(i=0;i<n;++i) printf("%d\n",lev[i]); } return 0; }
时间: 2024-10-20 08:30:18