原题: http://acm.hdu.edu.cn/showproblem.php?pid=1556
题目:
Color the ball
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13005 Accepted Submission(s): 6505
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 <iostream>
#include"cstdio"
#include"string.h"
using namespace std;
const int N= 100005;
struct node
{
int left;
int right;
int add;
int sum;
} tree[N*4];
int n,m;
int a[N];
void init()
{
memset(tree,0,sizeof(tree));
memset(a,0,sizeof(a));
}
//将下面更新的值返回上一层
void pushup(int id)
{
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
//将标记区间向下移动
void pushdown(int id)
{
tree[id*2].add=tree[id*2].add+tree[id].add;
tree[id*2].sum=tree[id*2].sum+(tree[id*2].right-tree[id*2].left+1)*tree[id].add;
tree[id*2+1].add=tree[id*2+1].add+tree[id].add;
tree[id*2+1].sum=tree[id*2+1].sum+(tree[id*2+1].right-tree[id*2+1].left+1)*tree[id].add;
tree[id].add=0;
}
//建树的时候每次建完下一层要向上层赋值
void build(int id,int l,int r)
{
tree[id].left=l;
tree[id].right=r;
tree[id].add=0;
tree[id].sum=0;
if(l==r)
{
tree[id].sum=a[l];
return;
}
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
void add(int id,int l,int r,int val)
{
//如果当前区间完全被包含,只更新当前区间的总和
//并对该区间做增加标记
if(tree[id].left>=l&&tree[id].right<=r)
{
tree[id].add=tree[id].add+val;
tree[id].sum=tree[id].sum+(tree[id].right-tree[id].left+1)*val;
return ;
}
//如果当前区间没有被包含
if(tree[id].right<l||tree[id].left>r) return ;
//如果当前区间部分被包含,标记下移
if(tree[id].add) pushdown(id);
//更新左右子区间
add(id*2,l,r,val);
add(id*2+1,l,r,val);
//更新完再把结果返回上层
pushup(id);
}
void update(int id)
{
//把每个区间的都加到结果上去
for(int i=tree[id].left;i<=tree[id].right;i++)
a[i]=a[i]+tree[id].add;
if(tree[id].left!=tree[id].right)
{
update(id*2);
update(id*2+1);
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF,n)
{
init();
char s[10];
build(1,1,n);
for(int i=1; i<=n; i++)
{
int a,b;
scanf("%d %d",&a,&b);
add(1,a,b,1);
}
update(1);
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
//fclose(stdin);
return 0;
}