• 蓝桥杯Log大侠(线段树单点区间更新)


    标题:Log大侠

        atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠。

        一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力...

        变换的规则是: 对其某个子序列的每个整数变为: [log_2 (x) + 1]  其中 [] 表示向下取整,就是对每个数字求以2为底的对数,然后取下整。     例如对序列 3 4 2 操作一次后,这个序列会变成 2 3 2。         drd需要知道,每次这样操作后,序列的和是多少。

    【输入格式】 第一行两个正整数 n m 。 第二行 n 个数,表示整数序列,都是正数。 接下来 m 行,每行两个数 L R 表示 atm 这次操作的是区间 [L, R],数列序号从1开始。

    【输出格式】 输出 m 行,依次表示 atm 每做完一个操作后,整个序列的和。

    例如,

    输入:

    3 3

    5 6 4

    1 2

    2 3

    1 3

    程序应该输出:

    10

    8

    6

    【数据范围】 对于 30% 的数据, n, m <= 10^3 对于 100% 的数据, n, m <= 10^5

    资源约定: 峰值内存消耗 < 256M CPU消耗  < 1000ms

    #include"cstdio"
    #include"cmath"
    #include"algorithm"
    using namespace std;
    const int MAXN=100005;
    typedef long long LL;
    struct node{
        int l,r;
        LL sum;
    }segTree[MAXN*3];
    int cnt;
    void build(int rt,int l,int r)
    {
        segTree[rt].l=l;
        segTree[rt].r=r;
        if(l==r)
        {
            scanf("%lld",&segTree[rt].sum);
            if(segTree[rt].sum==1)
            {
                cnt++;//统计数值1的个数 ,方便优化程序 
                segTree[rt].sum++;//将所有1均变为2,防止1干扰程序优化 
            }
            return ;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);
        build((rt<<1)|1,mid+1,r);
        segTree[rt].sum=segTree[rt<<1].sum+segTree[(rt<<1)|1].sum;
    }
    
    void update(int rt,int l,int r)
    {
        if(segTree[rt].sum==2*(segTree[rt].r-segTree[rt].l+1))    return ;//优化:不超过4轮,不小于2的整数在均变为2 
        
        if(segTree[rt].l==segTree[rt].r)
        {
            segTree[rt].sum=(LL)(log2(segTree[rt].sum*1.0)+1);
            return ;
        }
        
        int mid=(segTree[rt].l+segTree[rt].r)>>1;
        
        if(r<=mid)    update(rt<<1,l,r);
        else if(mid<l)    update((rt<<1)|1,l,r);
        else{
            update(rt<<1,l,mid);
            update((rt<<1)|1,mid+1,r);
        }
        segTree[rt].sum=segTree[rt<<1].sum+segTree[(rt<<1)|1].sum;
    }
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            update(1,x,y);
            printf("%lld
    ",segTree[1].sum-cnt);
        }
    }


     

  • 相关阅读:
    第一课 GCC入门
    第二课客户端链接Linux系统
    2014目标!!!!
    第一课Linux系统安装知识(2)
    android开发系列之ContentObserver
    android开发系列之数据存储
    android开发系列之视频断点续传
    稻盛和夫系列之活法一
    android开发系列之使用xml自定义控件
    android开发系列之MVP设计模式
  • 原文地址:https://www.cnblogs.com/program-ccc/p/5125331.html
Copyright © 2020-2023  润新知