【线段树】Color the ball ---经典题,还可用树状数组。。。

本文介绍了一种基于树状数组实现的区间更新与查询算法。该算法通过预先构建树形结构来高效处理区间更新及单点查询操作,适用于解决大规模数据集上的动态更新与查询问题。文章详细展示了算法的核心数据结构定义、初始化过程、区间更新逻辑以及单点查询方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include <stdio.h>
using namespace std;
#define maxn 100010
int n,a,b;

struct node{
	int l,r,s;
}ac[maxn*3+5];

//建树 
void build(int k,int l,int r){
	ac[k].l=l;
	ac[k].r=r;
	ac[k].s=0;//根节点(编号为1) 
	if(ac[k].l==ac[k].r){//到达叶子节点(例如1--1) 
		return ;
	}		
	
	int mid=(ac[k].l+ac[k].r)/2;
	build(k*2,l,mid);//建设左边子树 
	build(k*2+1,mid+1,r);//建设左边子树
}

//区间更新(更新节点的s的数值) 
void up(int k,int l,int r){
	if(ac[k].l==l && ac[k].r==r){//寻到要更新的区间(编号为k的节点),把k的s加一; 
		ac[k].s++;
		return ;
	}
	if(ac[k].l==ac[k].r){
		return ;
	}
	
	int mid=(ac[k].l+ac[k].r)/2;
	//要更新的区间在左子树下 
	if(mid>=r){
		up(k*2,l,r);
	}
	else if(mid<l){
		up(k*2+1,l,r);
	}
	//区间在左子树和右子树之间 
	else{
	up(k*2,l,mid);
	up(k*2+1,mid+1,r); 
	}
}
//查询 
int query(int k,int l,int r){
	
	if(ac[k].l==l && ac[k].r==r)
		return ac[k].s;
	if(ac[k].l==ac[k].r){//已经寻到叶子节点 
		return 0;
	}
	
		int mid=(ac[k].l+ac[k].r)/2;
		if(mid>=r){
			return ac[k].s+query(k*2,l,r);//l和r此刻数值相同表示叶子节点 
		}
		else if(mid<l){
				return ac[k].s+query(k*2+1,l,r);//每次加上前面的 
		}
		else{
			return ac[k].s+query(k*2,l,mid)+query(k*2+1,mid+1,r);
		} 
}
int main(){


    while(scanf("%d",&n)!=EOF){
    	if(n==0) break;
        build(1,1,n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a,&b);
            up(1,a,b);
     
		}
        for(int i=1;i<=n;i++){          
            printf("%d",query(1,i,i));
            if(i!=n) printf(" ");
  
        }
        printf("\n");
        
    }
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值