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,输入结束。
当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大概思路:因为这类树状数组是修改区间求点的,所以得考虑修改问题。记住修改那些该修改的,恢复那些不该修改的。至于sum(i),即为位置i 的修改次数,这点调试很长时间。很神奇,具体自己调试去吧。千万不要天真以为c[i],存的是修改次数。仔细调试,细细品味!#include<stdio.h> #include<string.h> int c[100001]; //因为从1开始,所以数组得多开一个 WA了一次 int n; int lowbit(int x) { return x&(-x); } void update(int x,int zhi) //向前修改 { while(x>0) { c[x]=c[x]+zhi; x=x-lowbit(x); } } int sum(int x) //求和即为修改次数 { int res=0; while(x<=n) { res=res+c[x]; x=x+lowbit(x); } return res; } int main() { int i; int x,y; while(scanf("%d",&n)!=EOF&&n) { memset(c,0,sizeof(c)); for(i=0;i<n;i++) { scanf("%d%d",&x,&y); update(y,1); //从右区间向前修改 update(x-1,-1); //从左区间向前修改,恢复那些不需要修改的值 } for(i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%d",sum(i)); //sum(i)就是修改的次数,这点很神奇,需细细品味! } printf("\n"); } return 0; } /* 开始这样写 果断TLE for(j=x;j<=y;j++) //把区间转化为点 { update(j,1); //先向下修改,把区间内数加上 m=j; //再向后修改,把不必要修改的区间减去 m=m-lowbit(m); while(m>0) { c[m]=c[m]-1; m=m-lowbit(m); } } */