Color the ball
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 29526 Accepted Submission(s): 14356
Problem Description
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a
b(a <=
b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?
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
//注意laz[]要和线段树数组开一样大小
#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
const int n = ;
using namespace std;
void pushdown(int num);
int tre[n * ];
int laz[n*];
void update(int num, int le, int ri, int x, int y,int z)
{
if (x <= le && y >= ri)
{
tre[num] = tre[num] + z;//初值为0,z=1
laz[num] = laz[num] + z;
return;
}
pushdown(num);
int mid = (le + ri) / ;
if (x <= mid)
update(num * , le, mid, x, y, z);
if (y > mid)
update(num * + , mid + , ri, x, y, z);
}
void pushdown(int num)
{
if (laz[num] != )
{
tre[num * ] += laz[num];
tre[num * + ] += laz[num];
laz[num * ] += laz[num];
laz[num * + ] += laz[num];
laz[num] = ;
}
}
int query(int num, int le, int ri, int x)
{
if (le == ri)
{
return tre[num];
}
pushdown(num);
int mid = (le + ri) / ;
if (x <= mid)
return query(num * , le, mid, x);
else
return query(num * + , mid + , ri, x);
}
int main()
{
int t;
while (cin >> t)
{
memset(tre, , sizeof(tre));
memset(laz, , sizeof(laz));//初始化延迟标记
for (int i = ; i < t; i++)
{
int x, y;
cin >> x >> y;
update(, , t, x, y, );
cout << query(, , n, x) << endl;
}
}
return ;
}
用结构体储存数据
#include <stdio.h>
#include<iostream>
#include <string.h>
using namespace std;
struct node
{
int left, right, count;
}c[ * ];
int sum[];
void build(int le, int ri, int root)
{
c[root].left = le;
c[root].right = ri;
c[root].count = ;
if (le == ri)
return;
int mid = (le + ri) / ;
build(le, mid, root * );
build(mid + , ri, root * + );
}
void update(int le, int ri, int root)//更新
{
if (c[root].left == le && c[root].right == ri)//只需要在这个区间+1就行了,节省时间,不用找到每个数
{
c[root].count++;
return;
}
int mid = (c[root].left + c[root].right) / ;
if (mid<le)//如果更新区间在右子树上,就只更新右区间
update(le, ri, root * + );
else if (mid >= ri)//更新左子树
update(le, ri, root * );
else//更新区间即在右子树上,又在左子树上
{
update(le, mid, root * );
update(mid + , ri, root * + );
}
}
void tosum(int root)//求和、记录每个气球被涂过的次数
{
for (int i = c[root].left; i <= c[root].right; i++)
sum[i] += c[root].count;
if (c[root].left == c[root].right)
return;
tosum(root * );//通过子节点来更新父节点
tosum(root * + );
}
int main()
{
int n;
while (scanf("%d", &n) && n)
{
memset(sum, , sizeof(sum));
memset(&c, , sizeof(&c));
build(, n, );
for (int i = ; i<n; i++)
{
int le, ri;
scanf("%d %d", &le, &ri);
update(le, ri, );
}
tosum();
printf("%d", sum[]);
for (int i = ; i <= n; i++)
printf(" %d", sum[i]);
printf("\n");
}
return ;
}