其实是很简单的一道题,由于一开始不会线段树的区间更新所以一直WA,网上题解大部分都是树状数组搞得,道不同啊,所以一直自己死扣,终于A了,真心不容易;
好了,先说说线段树的区间更新,这是点更新的扩展,点更新很简单,当然你可以用个循环加点更新,不过,效率太慢,如果有上千条上万条操作肯定T了,所以伟大的码农们想到了一个方法,懒惰标记,简单来说就是更新的时候你用到那一层就更新到那一层,用不到的就标记下来,等下次用到了再更新,同时消除标记;
看到这肯定迷糊了,还是来道题学习一下吧;
N个气球排成一排,从左到右依次编号为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
Sample Output
1 1 1
3 2 1
很简单的题吧,粉刷气球,每次操作把相应区间内的气球粉刷一遍,问最后每个气球分别被粉刷了多少遍;
来看看代码;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#define MAX 100000+5
using namespace std;
int segtree[MAX<<2]; //树结点,用来储存气球的粉刷次数,由于此题只与叶结点有关,所以中间节点的值不需要关心;
int lazy[MAX<<2]; //懒惰标记;
int N; //气球个数;
void build(int node, int left, int right){//建立线段树,叶结点全部为零;
if(left==right){
segtree[node]=0;
return;
}
int mid=(left+right)>>1;
build(node<<1, left, mid);
build(node<<1|1, mid+1, right);
}
void pushdown(int node, int left, int right){//如果该层被标记,那么对他的左右孩子更新;
if(left!=right){//这句判断一定要加,不然会RE,血淋淋得教训啊;
segtree[node<<1]+=lazy[node];//更新左孩子;
segtree[node<<1|1]+=lazy[node];//更新右孩子;
lazy[node<<1|1]+=lazy[node]; //把标记传入下一层;
lazy[node<<1]+=lazy[node];
}
lazy[node]=0; //消除标记;
}
void update(int node, int left, int right, int l, int r, int add){//区间更新;传参:树根,区间范围,需要更新的区间,每个数要增加的值;
if(lazy[node]) pushdown(node, left, right);//先判断该层是否被标记,如果被标记就更新一次;
if(l>right || r<left) return;
if(l<=left && r>=right){
lazy[node]+=add; //找到更新区间后标记该层,表示该层以下需要被更新,需要增加的值为lazy内的值;
segtree[node]+=lazy[node]; //更新该层;
return;
}
int mid=(left+right)>>1;
update(node<<1, left, mid, l, r, add);
update(node<<1|1, mid+1, right, l, r, add);
}
void query(int node, int left, int right){
if(lazy[node]) pushdown(node, left, right);//不管查询还是更新每次都要先判断该层是否被更新;
if(left==right){ //if左右孩子相等,该点是叶结点,输出叶结点;
if(left==N) printf("%d\n",segtree[node]);
else printf("%d ",segtree[node]);
return;
}
int mid=(left+right)>>1;
query(node<<1, left, mid);
query(node<<1|1, mid+1, right);
}
int main(){
while(scanf("%d",&N),N!=0){
int a, b;
int i;
build(1, 1, N);
memset(lazy, 0, sizeof(lazy));
for(i=1; i<=N; i++){
scanf("%d%d",&a,&b);
update(1, 1, N, a, b, 1);
}
query(1, 1, N);
}
return 0;
}