zoukankan      html  css  js  c++  java
  • codevs2492 上帝造题的七分钟 2

    2492 上帝造题的七分钟 2

    题目描述 Description

      XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。

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

    输入描述 Input Description

      第一行一个整数n,代表数列中数的个数。
      第二行n个正整数,表示初始状态下数列中的数。
      第三行一个整数m,表示有m次操作。
      接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。
      UPD:注意数据中有可能l>r,所以遇到这种情况请交换l和r。

    输出描述 Output Description

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

    样例输入 Sample Input

    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

    样例输出 Sample Output

    19
    7
    6

    数据范围及提示 Data Size & Hint

      对于30%的数据,1<=n,m<=1000,数列中的数不超过32767。
      对于100%的数据,1<=n,m<=100000,1<=l,r<=n,数列中的数大于0,且不超过1e12。
      注意l有可能大于r,遇到这种情况请交换l,r。



    来源:Nescafe 20

    【思路】

          区间查询+打标记。

      一个关键的思想就是一个数被反复开方并向下取整最终会变为1,如果一个数变成1就不需要对它操作了。

      对于区间开方操作,对于区间中的每一个点都进行操作如果为1则下次不再操作。

      实现1:

             BIT+“并查集”。

    【代码1】

     1 //341ms
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     7 using namespace std;
     8 
     9 typedef long long LL;
    10 const int maxn = 200000+10;
    11 
    12 LL a[maxn],p[maxn];
    13 int n,m;
    14 
    15 LL read() {
    16     char c=getchar();
    17     while(!isdigit(c)) c=getchar();
    18     LL x=0;
    19     while(isdigit(c)) {
    20         x=x*10+c-'0';
    21         c=getchar();
    22     }
    23     return x;
    24 }
    25 
    26 LL c[maxn];
    27 int lowbit(int x) { return x&(-x); }
    28 LL Sum(LL x) {
    29     LL res=0;
    30     while(x>0) {
    31         res += c[x];
    32         x-=lowbit(x);
    33     }
    34     return res;
    35 }
    36 void Add(int x,LL d) {
    37     while(x<=n) {
    38         c[x] += d;
    39         x += lowbit(x);
    40     }
    41 }
    42 int find(int x) {
    43     return x==p[x]?x:p[x]=find(p[x]);
    44 }
    45 
    46 int main() {
    47     n=read();
    48     FOR(i,1,n) a[i]=read(),Add(i,a[i]);
    49     FOR(i,1,n+1) p[i]=i;                //n+1为哨兵 
    50     m=read();
    51     LL u,v,w;
    52     FOR(i,1,m) {
    53         w=read(),u=read(),v=read();
    54         if(u>v) swap(u,v);
    55         
    56         if(w)
    57             printf("%lld
    ",Sum(v)-Sum(u-1));
    58         else 
    59         {
    60             for(int j=find(u);j<=v;j=find(j+1)) {
    61                 LL s=sqrt(a[j]);
    62                 Add(j,s-a[j]);
    63                 a[j]=s;
    64                 if(s==1) {
    65                     p[j]=j+1;
    66                     if(j==v) break;
    67                 }
    68             }
    69         }
    70     }
    71     return 0;
    72 }
    View Code

      实现2:

             线段树+结点标记

    【代码2】

     1 //399ms
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     7 using namespace std;
     8 
     9 typedef long long LL;
    10 const int maxn = 500000+10;
    11 
    12 LL a[maxn],p[maxn];
    13 int n,m;
    14 
    15 LL read() {
    16     char c=getchar();
    17     while(!isdigit(c)) c=getchar();
    18     LL x=0;
    19     while(isdigit(c)) {
    20         x=x*10+c-'0';
    21         c=getchar();
    22     }
    23     return x;
    24 }
    25 
    26 LL sumv[maxn];
    27 bool f[maxn];
    28 void build(int u,int L,int R) {
    29     int lc=u*2,rc=u*2+1;
    30     if(L==R) {
    31         sumv[u]=a[L];
    32     }
    33     else {
    34         int M=L+(R-L)/2;
    35         build(lc,L,M);
    36         build(rc,M+1,R);
    37         sumv[u]=sumv[lc]+sumv[rc];
    38     }
    39 }
    40 int ya,yb;
    41 void update(int u,int L,int R) {
    42     int lc=u*2,rc=u*2+1;
    43     if(f[u]) return ;
    44     if(L==R) {
    45         sumv[u]=sqrt(sumv[u]);
    46         if(sumv[u]==1) f[u]=1;
    47     }
    48     else {
    49         int M=L+(R-L)/2;
    50         if(ya<=M) update(lc,L,M);
    51         if(M<yb)  update(rc,M+1,R);
    52         
    53         sumv[u]=sumv[lc]+sumv[rc];
    54         f[u]=f[lc]&&f[rc];
    55     }
    56 }
    57 LL query(int u,int L,int R) {
    58     int lc=u*2,rc=u*2+1;
    59     if(ya<=L && R<=yb) {
    60         return sumv[u];
    61     }
    62     else {
    63         int M=L+(R-L)/2;
    64         LL res=0;
    65         if(ya<=M) res+=query(lc,L,M);
    66          if(M<yb)  res+=query(rc,M+1,R);
    67          return res;
    68     }
    69 }
    70 
    71 int main() {
    72     n=read();
    73     FOR(i,1,n) a[i]=read();
    74     build(1,1,n);
    75     m=read();
    76     int w;
    77     while(m--) {
    78         w=read(),ya=read(),yb=read();
    79         if(ya>yb) swap(ya,yb);
    80         if(w)    printf("%lld
    ",query(1,1,n));
    81         else update(1,1,n);
    82     }
    83     return 0;
    84 }
    View Code
  • 相关阅读:
    MySQL查询缓存
    MySQL复制相关参数详解
    MySQL复制机制
    MySQL数据库的多表查询操作
    MySQL数据库单表查询基本操作及DML语句
    Hadoop大数据系列汇总
    MySQL数据库之日志功能详解
    MySQL数据库扫盲
    MySQL数据库之数据类型及基本使用详解
    MySQL数据库之日志管理
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4977619.html
Copyright © 2011-2022 走看看