题目链接:HDU - 1556
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个气球总共被涂色的次数。
题意描述:中文题,如上所述。
算法分析:这道题树状数组也可以做,但我刚读到题的时候想到的是线段树,所以先贴上线段树的写法。算是线段树比较水的一道题吧,直接标记每个节点被涂的次数然后输出即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 using namespace std; 9 const int maxn=100000+10; 10 11 int sum[maxn<<2],col[maxn<<2]; 12 int n,flag; 13 14 void PushDown(int rt,int m) 15 { 16 if (col[rt]!=0) 17 { 18 col[rt<<1] += col[rt]; 19 col[rt<<1|1] += col[rt]; 20 col[rt]=0; 21 } 22 } 23 24 void build(int l,int r,int rt) 25 { 26 col[rt]=0; 27 sum[rt]=0; 28 if (l==r) return ; 29 int mid=(l+r)>>1; 30 build(l,mid,rt<<1); 31 build(mid+1,r,rt<<1|1); 32 } 33 34 void update(int l,int r,int rt,int L,int R) 35 { 36 if (L<=l && r<=R) 37 { 38 col[rt] += 1; 39 return ; 40 } 41 PushDown(rt,r-l+1); 42 int mid=(l+r)>>1; 43 if (R<=mid) update(l,mid,rt<<1,L,R); 44 else if (L>mid) update(mid+1,r,rt<<1|1,L,R); 45 else 46 { 47 update(l,mid,rt<<1,L,R); 48 update(mid+1,r,rt<<1|1,L,R); 49 } 50 51 } 52 53 void query(int l,int r,int rt) 54 { 55 if (l==r) 56 { 57 if (!flag) flag=1; 58 else printf(" "); 59 printf("%d",col[rt]); 60 return ; 61 } 62 PushDown(rt,r-l+1); 63 int mid=(l+r)>>1; 64 query(l,mid,rt<<1); 65 query(mid+1,r,rt<<1|1); 66 } 67 68 int main() 69 { 70 while (scanf("%d",&n)!=EOF && n) 71 { 72 flag=0; 73 build(1,n,1); 74 int a,b; 75 for (int i=0 ;i<n ;i++) 76 { 77 scanf("%d%d",&a,&b); 78 update(1,n,1,a,b); 79 } 80 query(1,n,1); 81 printf(" "); 82 } 83 return 0; 84 }