• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

HDU 1556 Color the ball(线段树区间更新)

Color the ball

我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点

【题目链接】Color the ball

【题目类型】线段树区间更新

&题意:

N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?

&题解:

线段树区间更新模板题

【时间复杂度】\(O(nlogn)\)

&代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
int N;
int seg[maxn<<2];
int add[maxn<<2];

//在build 和 updata时需要向上更新
//query时不需要
inline void puup(int no)
{
    seg[no]+=seg[no<<1]+seg[no<<1|1];
}

//这题不需要建树 因为都是0
void build(int no,int b,int e)
{
    if (b==e){
        seg[no]=0;
        return ;
    }
    int m=b+e>>1;
    build(no<<1,b,m);
    build(no<<1|1,m+1,e);
    puup(no);
}

//query 和 updata时都要向下更新
void pudown(int no,int len)
{
    if (add[no]){
        //注意都是 +=
        add[no<<1]+=add[no];
        add[no<<1|1]+=add[no];
        //这seg节点里存的是与add相乘
        seg[no<<1]+=add[no]*(len-len/2);
        //左儿子存多的 右儿子存少的 可以自己弄一个奇数区间试一下
        seg[no<<1|1]+=add[no]*(len/2);
        add[no]=0;
    }
}

int query(int no,int b,int e,int l,int r)
{
    //第一种情况 在[l,r]中间
    if (l<=b&&e<=r){
        return seg[no];
    }
    int m=b+e>>1;
    pudown(no,e-b+1);
    ll re=0;
    //第二种情况 在疯狂的两个区间中
    if (l<=m)
        re+=query(no<<1,b,m,l,r);
    if (m<r)
        re+=query(no<<1|1,m+1,e,l,r);
    return re;
}

void updata(int no,int b,int e,int l,int r,int xx)
{
    //第一种情况 在[l,r]中间
    if (l<=b&&e<=r){
        add[no]+=xx;
        seg[no]+=e-b+1;
        return ;
    }
    pudown(no,e-b+1);
    int m=b+e>>1;
    //第二种情况 在疯狂的两个区间中
    if (l<=m)
        updata(no<<1,b,m,l,r,xx);
    if (m<r)
        updata(no<<1|1,m+1,e,l,r,xx);
    puup(no);
}

int main()
{
    while(cin>>N){
        if (N==0) break;
        //别忘初始化
        memset(seg,0,sizeof(seg));
        memset(add,0,sizeof(add));
//        build(1,1,N);
        for(int i=0;i<N;i++){
            int u,v;
            cin>>u>>v;
            updata(1,1,N,u,v,1);
        }
        for(int i=1;i<=N;i++){
            printf("%d%c",query(1,1,N,i,i),i==N?'\n':' ');
        }
    }
    return 0;
}
posted @ 2016-12-20 16:05  s1124yy  阅读(399)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3