树状数组入门题,题设比较简单
#include<stdio.h>
#define MAXC 32010
int C[MAXC], R[MAXC];
//树状数组模板
int lowbit(int t)
{
return t & (t ^ (t - 1)); //计算最小幂
}
int add(int i,int v)
{
while(i<MAXC) //取与C[i]有关的值添上增加的值
{
C[i]+=v;
i+=lowbit(i);
}
return 0;
}
int sum(int i)
{
int s=0;
while(i>0) //取与C[i]有关的值求和
{
s+=C[i];
i-=lowbit(i);
}
return s;
}
//树状数组模板
int main()
{
int n,i,x,y;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %d",&x,&y);
++R[sum(++x)];
//因为输入是有序的,所以可以立刻确定结果。又因为线段数组是从1开始的,所以x要总体右移一个单位长度
add(x,1);
//add和sum这两个操作先后没关系,因为sum中肯定不包括本身
}
for(i=0;i<n;i++)
printf("%d\n",R[i]);
return 0;
}
再附上线段树解法,但是速度要慢好多
#include <stdio.h>
#define L(t) ((t) << 1)
#define R(t) ((t) << 1 | 1)
#define MAXC 32010
struct SegTree
{
int l,r;
long long add, sum;
int getMid(){
return ( l + r) >>1;
}
int getDis(){
return r - l + 1;
}
} tree[MAXC << 2];
int arr[MAXC]; //存放X坐标
int R[MAXC]; //存放每个等级对应的结果数
void build(int left, int right, int t){ //递归构造
tree[t].l = left;
tree[t].r = right;
tree[t].add = 0;
tree[t].sum=0;
if(left == right){
return;
}
int mid = tree[t].getMid();
build(left, mid, L(t));
build(mid + 1, right, R(t));
}
void update(int left, int right, int a, int t){
if( left <= tree[t].l && right >= tree[t].r ){
tree[t].add += a; //若当前子树被目标区间覆盖 更新子树的sum和增量(在本次查询中,增量下行到此为之)
tree[t].sum += a * tree[t].getDis();
return;
}
if( tree[t].add ){ //向子结点传递增量,并更新其sum,最后清空自己的增量
tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;
tree[R(t)].sum += tree[R(t)].getDis() * tree[t].add;
tree[L(t)].add += tree[t].add;
tree[R(t)].add += tree[t].add;
tree[t].add = 0;
}
int mid = tree[t].getMid();
if(right <= mid ){
update(left, right, a, L(t)); //目标区间仅在左子树上
} else if (left > mid ){
update(left, right, a, R(t)); //目标区间仅在右子树上
} else {
update(left, right, a, L(t)); //目标区间同时在左右子树上
update(left, right, a, R(t));
}
tree[t].sum = tree[L(t)].sum + tree[R(t)].sum ; //更新父结点的sum
}
long long query(int left, int right, int t){
if(left <= tree[t].l && right >= tree[t].r ){
return tree[t].sum;
}
if( tree[t].add ){ //这一段和update函数一样,是一个pushDown
tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;
tree[R(t)].sum += tree[R(t)].getDis() * tree[t].add;
tree[L(t)].add += tree[t].add;
tree[R(t)].add += tree[t].add;
tree[t].add = 0;
}
int mid = tree[t].getMid();
if(right <= mid ){
return query(left, right, L(t));
} else if( left > mid ){
return query(left, right, R(t));
} else {
return query(left, mid ,L(t)) +
query(mid + 1, right, R(t));
}
}
int main()
{
int n,i,x,y;
scanf("%d",&n);
build(1,MAXC,1);
int k;
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
x++;
k=query(1,x,1);
R[k]++;
update(x,x,1,1);
}
for (i=0;i<n;i++)
printf("%d\n",R[i]);
return 0;
}