hdu 1541 Stars(线段树单点更新,区间查询)

题意:求坐标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
",lev[i]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/gongpixin/p/4739084.html