HDU -1556 Color the ball -线段树-成段更新
来源:互联网 发布:剑网三男神捏脸数据 编辑:程序博客网 时间:2024/04/29 21:20
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
题意:
对于n个气球编号分别为1,2,3……n进行上色,每次上色为一个区间a~b,问n次操作后,每个气球分别被上色多少次。
分析:
用线段树做,只需要每次更新都适当地做标记,最后将所有标记都下沉至叶子结点,此时,叶子结点的标记值便是该气球被上色的次数,直接输出各个叶子结点的值即可。
说一下我对标记下沉的理解,以此题为例,假设有如下数据:
5
1 3 ——①
1 2 ——②
1 1 ——③
1 4 ——④
1 5 ——⑤
那么操作流程分别为
建树:
可得pos_rt[0]=8,pos_rt[1]=9, pos_rt[2]=5, pos_rt[3]=6, pos_rt[4]=7
而后更新:
① [1 3]做标记,sign[2]++
② [1 2]做标记,[1 3]标记下沉:sign[4]+=sign[2],sign[5]+=sign[2],sign[4]++;sign[2]=0;
③ [1 1]做标记,[1 2]标记下沉: sign[8]+=sign[4],sign[9]+=sign[4],sign[8]++;sign[4]=0;
④ [1 4]做标记,标记[1 3],[4 4];
⑤ [1 5]做标记
此时标记全都做完了,然后对所有标记进行下沉到叶子结点
输出每个叶子结点的标记,及每个气球的上色次数。
代码:
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int pos_rt[100001];//用来记录气球编号对应的下标rt int sign[400000];//各rt的标记 int size;//气球的编号个数 void _build(int l,int r,int rt)//建树(其实我的建树只是用来查找记录气球编号的rt的) { if(l==r) { pos_rt[size++]=rt;//找到叶子结点时,记录下rt,以便输出 return; } int m=(l+r)>>1; _build(l,m,rt<<1); _build(m+1,r,rt<<1|1); } void _downUpDate(int rt)//标记下沉 { if(sign[rt])//当有标记时 { sign[rt<<1]+=sign[rt];//左子树标记更新 sign[rt<<1|1]+=sign[rt];//右子树标记更新 sign[rt]=0;//删除当前rt的标记 } } void _upDate(int L,int R,int l,int r,int rt)//用以更新下沉标记 { if(L<=l&&r<=R)//区间包含,当前区间的标记+1 { sign[rt]++; return; } _downUpDate(rt);//当前rt被用到,故下沉标记到左右子树 int m=(l+r)>>1; if(L<=m) _upDate(L,R,l,m,rt<<1); if(R>m) _upDate(L,R,m+1,r,rt<<1|1); } void _pushDown(int l,int r,int rt)//所有标记下沉至叶子结点 { if(l==r)//叶子结点回溯 return; _downUpDate(rt);//非叶子结点下沉标记 int m=(l+r)>>1; _pushDown(l,m,rt<<1); _pushDown(m+1,r,rt<<1|1); } int main() { int n,a,b,i; while(scanf("%d",&n),n) { size=0; memset(pos_rt,0,sizeof(pos_rt)); memset(sign,0,sizeof(sign)); _build(1,n,1); for(i=0;i<n;i++) { scanf("%d%d",&a,&b); _upDate(a,b,1,n,1); } _pushDown(1,n,1); for(i=0;i<size-1;i++)//直接输出各叶子结点的标记的值,对应的rt已用pos_rt数组记录 printf("%d ",sign[pos_rt[i]]); printf("%d\n",sign[pos_rt[size-1]]); } return 0; }
- HDU -1556 Color the ball -线段树-成段更新
- hdu 1556 Color the ball(成段更新)
- HDU 1556 Color the ball 线段树更新区间查点
- HDU - 1556 Color the ball (线段树 + 区间更新)
- HDU 1556 Color the ball 线段树 区间更新
- HDU 1556 Color the ball(线段树区间更新)
- HDU 1556 Color the ball(线段树区间更新)
- HDU 1556-Color the ball(线段树区间更新)
- HDOJ 1556 Color the ball 线段树 : 成段更新 单点查询
- HDU 1556 Color the ball 线段树
- HDU 1556 Color the ball (线段树)
- HDU 1556 Color the ball 线段树
- hdu 1556 Color the ball(线段树)
- hdu 1556 Color the ball 线段树
- HDU 1556 Color the ball 线段树
- HDU 1556 Color the ball [线段树]
- HDU 1556 Color the ball (线段树)
- hdu - 1556 (Color the ball 线段树)
- 8-10 EXT入门
- NEFU 115 斐波那契的整除(数论&整除推导)
- Android应用开发之activity的创建
- hdu 4578
- Eclipse Error: A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in o
- HDU -1556 Color the ball -线段树-成段更新
- ural 1658. Sum of Digits
- 如何配置java环境?
- 刷新当前页面的几种方法
- 父div内有浮动的子div,父div的宽度不会被子div撑开
- Windows 编程之服务-2
- Android 源码/NDK下编译C/C++的可执行文件
- (js,jQuery)获取父窗、子窗的iframe
- Topic-Sensitive PageRank(主题敏感的PageRank )