• Log大侠 蓝桥杯(势能线段树)


    试题 历届真题 Log大侠【第五届】【决赛】【B组】
         
    资源限制
    内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s
      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
    View problem

    思路:

    • 这种类型就是线段树嘛
    • 为了优化时间复杂度,发现一直取log 很容易就把 val的值变得特别小, 到 2和1就不变了,对他们取log2 +1,还是原值
    • 所以就是一个势能线段树,对于全是1或者2的区间就不用管

    关键吐槽:

    最后4个大数据, 第一个 L,R 和蓝桥杯数据对不上,其他都对的上,就很tm离谱,而且暴力题解和我的答案是一样的,我又找了很多篇其他题解都这样,我就搞不明白了!!!!

    如果真是蓝桥杯的数据问题,就是纯纯浪费时间!!!!!,

    如果不是,求大佬告诉我哪错了

    #include <bits/stdc++.h>
    using namespace std;
    #define ri register int
    #define M 100005
    
    template <class G> void read(G &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=f?-x:x;
        return ;
    }
    
    
    int n,m;
    long long val[M];
    struct dian{
        int l,r;
        long long val;
        int flag;
    }p[M*4];
    void build(int l,int r,int i)
    { 
        p[i].l=l;p[i].r=r;
        if(l==r)
        {
            p[i].val=val[l];
            if(p[i].val==1||p[i].val==2) p[i].flag=1;
            else p[i].flag=0;
            return ;
        }
       int mid=(l+r)>>1;
       build(l,mid,i<<1);
       build(mid+1,r,i<<1|1);
       p[i].val=p[i<<1].val+p[i<<1|1].val;
       p[i].flag=p[i<<1].flag&p[i<<1|1].flag;
    }
    void xiu(int l,int r,int i)
    {
        if(l>p[i].r||r<p[i].l) return ;
        if(p[i].flag) return ;
        if(l<=p[i].l&&r>=p[i].r)
        {
            if(p[i].l==p[i].r)
           {
            long long  tmp=0;
            while(p[i].val)
            {
                tmp++;
                p[i].val>>=1;
            }
            p[i].val=tmp;
            if(p[i].val==1||p[i].val==2) p[i].flag=1;
            return ;
           }
        }
    
         xiu(l,r,i<<1);
         xiu(l,r,i<<1|1);
        p[i].val=p[i<<1].val+p[i<<1|1].val;
        p[i].flag=p[i<<1].flag&p[i<<1|1].flag;
    
    }
    int main(){
        
        
        read(n);read(m);
        for(ri i=1;i<=n;i++)
        {
            read(val[i]);
        }
        build(1,n,1);
        for(ri i=1;i<=100;i++)
        {
            int l,r;
            read(l);read(r);
            xiu(l,r,1);
            printf("%lld\n",p[1].val);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Sql Server 收缩日志文件原理及always on 下的实践
    SQL Agent服务无法启动如何破
    Sql Server Always On 读写分离配置方法
    SQL SERVER 9003错误解决方法 只适用于SQL2000
    SQL Server 数据库分离与附加
    SQL SERVER 的模糊查询 LIKE
    sqlserver 时间格式函数详细
    浅谈SQL Server中的三种物理连接操作
    谈一谈SQL Server中的执行计划缓存(下)
    asp.net获取当前系统的时间
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/16338636.html
Copyright © 2020-2023  润新知