• 上帝造题的七分钟2


    题目描述

    XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。
    "第一分钟,X说,要有数列,于是便给定了一个正整数数列。
    第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
    第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
    第四分钟,彩虹喵说,要是noip难度,于是便有了数据范围。
    第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
    第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
    第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。"
    ——《上帝造题的七分钟·第二部》
    所以这个神圣的任务就交给你了。

    输入

    第一行一个整数n,代表数列中数的个数。
    第二行n个正整数,表示初始状态下数列中的数。
    第三行一个整数m,表示有m次操作。
    接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。

    输出

    对于询问操作,每行输出一个回答。

    样例输入

    10
    1 2 3 4 5 6 7 8 9 10
    5
    0 1 10
    1 1 10
    1 1 5
    0 5 8
    1 4 8
    

    样例输出

    19
    7
    6
    

    提示

    1:对于100%的数据,1<=n<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。

    2:数据不保证L<=R 若L>R,请自行交换L,R,谢谢! 

    题解

       看到这个题就唤起了对某些叫“相逢是问候”的题的回忆~虽然那个题的定理没有搞懂,不过总之是“操作到某种境界就不用再改了”。毕竟开方数据小得很快,手模了一下样例,这么两行操作已经大部分是1了,这暗示也够明显的。然后就果断线段树,但是这时候做了个愚蠢的决定:用bool型标记每一个值是否已经是1。后来回来调,看着一堆bool很不顺眼,决定换成链表,心里还有点疑虑链表会不会出问题。事实证明链表倒是没出问题,但是既然是单点修改并不会比bool优太多。只要把这个傻标记放到线段树里面,对于标记整个覆盖的区间直接停止修改就行了。这道题主要给了我一个教训:是区间修改的就尽量区间做,拆成单点就算有特殊规律也会慢到TLE。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int sj=1000010;
    int n,m;
    long long a[sj];
    struct XDS
    {
         long long num;
         int le,ri;
         bool ma;
    }t[sj*4];
    void bte(int x,int z,int y)
    {
         t[x].le=z;
         t[x].ri=y;
         if(z==y)
         {
            t[x].num=a[z];
            if(a[z]==1)
              t[x].ma=1;
            else
              t[x].ma=0;
            return;
         }
         int mid=(z+y)>>1;
         bte(x<<1,z,mid);
         bte((x<<1)+1,mid+1,y);
         t[x].num=t[x<<1].num+t[(x<<1)+1].num;
         if(t[x<<1].ma&&t[(x<<1)+1].ma)
           t[x].ma=1;
    }
    long long query(int x,int z,int y)
    {
         if(z==t[x].le&&y==t[x].ri)
           return t[x].num;
         int mid=(t[x].le+t[x].ri)>>1;
         if(mid>=y) return query(x<<1,z,y);
         if(mid<z)  return query((x<<1)+1,z,y);
         return query(x<<1,z,mid)+query((x<<1)+1,mid+1,y);
    }
    void update(int x,int l,int r)
    {
         if(t[x].ma) return;
         if(t[x].le==t[x].ri)
         {
            t[x].num=floor(sqrt(t[x].num));
            if(t[x].num==1)
              t[x].ma=1;
            return;
         }
         int mid=(t[x].le+t[x].ri)>>1;
         if(r<=mid) update(x<<1,l,r);
         if(l>mid)  update((x<<1)+1,l,r);
         if(l<=mid&&r>mid)  
         {
            update(x<<1,l,mid);
            update((x<<1)+1,mid+1,r);
         }
         t[x].num=t[x<<1].num+t[(x<<1)+1].num;
         if(t[(x<<1)+1].ma&&t[x<<1].ma)
           t[x].ma=1;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
          scanf("%lld",&a[i]);
        scanf("%d",&m);
        bte(1,1,n);
        int op,a1,a2,tp;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&op,&a1,&a2);
            if(a1>a2)
            {
               tp=a1;
               a1=a2;
               a2=tp;
            }
            if(op)
               printf("%lld
    ",query(1,a1,a2));
            if(!op)
               update(1,a1,a2);
        }
        return 0;
    }
     
  • 相关阅读:
    微信小程序之阻止冒泡事件
    微信小程序之生成二维码
    微信小程序之数据缓存和数据获取
    微信小程序之分享功能
    抽丝剥茧——策略设计模式
    抽丝剥茧——单例设计模式
    抽丝剥茧——备忘录设计模式
    手把手教你Smarty缓存技术(转)
    二级域名session 共享方案(转)
    MySQL监控、性能分析——工具篇
  • 原文地址:https://www.cnblogs.com/moyiii-/p/7182937.html
Copyright © 2020-2023  润新知