杭电1556 线段树

Problem Description
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 <string.h>
#include <stdio.h>
#define max(a,b) a>b?a:b
#define  N  1005
#include<iostream>
using namespace std;
struct node {
    int l,r,sum,n,az;
} t[400000];
int n,m;
void build (int i,int l,int r) {
    t[i].l=l;
    t[i].r=r;
    t[i].sum=0;
    if(l==r) {
        return;
    }
    int mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
}
void update(int i,int l,int r) {
    if(t[i].l==l&&t[i].r==r) {//这里是核心,类似懒惰标记,在中序遍历时向下附加
        t[i].sum+=1;
        return ;
    }
    int mid=(t[i].l+t[i].r)/2;
    if(r<=mid)
        update(i*2,l,r);
    else if(l>mid)
        update(i*2+1,l,r);
    else {
        update(i*2,l,mid);
        update(i*2+1,mid+1,r);
    }
}
void sum(int i) {//二叉树中序遍历
    if(t[i].l==t[i].r) {
        m++;
        printf("%d",t[i].sum);
        if(m!=n)printf(" ");
        return ;
    }
    t[i*2].sum+=t[i].sum;
    t[i*2+1].sum+=t[i].sum;
    sum(i*2);
    sum(i*2+1);

}
int main() {
    while(cin>>n&&n) {
        build(1,1,n);
        for(int j=0; j<n; j++) {
            int x,y;
            scanf("%d%d",&x,&y);
            update(1,x,y);
        }
        m=0;
        sum(1);
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(杭电1556 线段树)