线段树


用线段树的方法解决区间操作类的问题很好用。如果用一般的数组来执行操作那么数据量只要过大,运行的时间就会超出系统所设定的通过时间,而线段树的操作是用区间的操作方法,并不是去改变每一个数组的元素;下面举个例子说明一下;


个气球排成一排,从左到右依次编号为1,2,3....N. 每次给定2 个整数a b(a <= b),lele 便为骑上他的 小飞鸽" 牌电动车从气球a 开始到气球b 依次给每个气球涂一次颜色。但是N 次以后lele 已经忘记了第I个气球已经涂过几次颜 色了,你能帮他算出每个气球被涂过几次颜色吗?

Input

每个测试实例第一行为一个整数N,(N <= 100000). 接下来的N 行,每行包括2 个整数a b(1 <= a <= b <= N) 。
当N = 0 ,输入结束。

 

 

Output

每个测试实例输出一行,包括N 个整数,第I 个数代表第I 个气球总共被涂色的次数。

 

 

Sample Input

3

1 1

2 2

3 3

3

1 1

1 2

1 3

0


如果用数组记录每个气球被涂的次数,如果执行的操作有M次,那么每次都要循环的去给每个气球涂色,运行的时间是N*M次的;

但是用线段树来记录每个区间的操作情况,只需要区间进行操作;

#include<stdio.h>
#include<string.h>
#define MAXN 100005
struct ST
{
	int l,r,sum;
}st[MAXN*3];
int nn;
void build(int ll,int rr,int n)//建立线段树
{
	st[n].l=ll;
	st[n].r=rr;
	st[n].sum=0;
	if (ll==rr) return ;
	int mid=(ll+rr)/2;
	build(ll,mid,2*n);
	build(mid+1,rr,2*n+1);
};
void color(int ll,int rr,int n)对线段树进行操作
{
	if (st[n].l==ll&&st[n].r==rr) {st[n].sum++;return ;}
	int mid=(st[n].l+st[n].r)/2;
	if (rr<=mid) color(ll,rr,2*n);
	else
	if (ll>=mid+1) color(ll,rr,2*n+1);
	else
	{
		color(ll,mid,2*n);
		color(mid+1,rr,2*n+1);
	}
}
void out(int n,int sum)//输出对应的线段树的值
{
	if (st[n].l==st[n].r) {printf("%d",sum+st[n].sum);if (st[n].l!=nn) printf(" ");return;}
	out(2*n,sum+st[n].sum);
	out(2*n+1,sum+st[n].sum);
}
int main()
{
	int i,p,q;
	while (scanf("%d",&nn)&&nn)
	{
		build(1,nn,1);
		for (i=1;i<=nn;++i)
		{
			scanf("%d%d",&p,&q);
			color(p,q,1);
		}
		out(1,0);
		printf("/n");
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值