BZOJ3038: 上帝造题的七分钟2

3038: 上帝造题的七分钟2

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1715  Solved: 728
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

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

HINT

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


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

Source

对于求根号,直接暴力到线段树叶子即可,可以证明最多根号loglogn次就能减到1

正当我以为自己写的有瑕疵打算对拍,而且即将打完时,突然想起

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

mdzz

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <queue>
  8 #include <vector>
  9 #define min(a, b) ((a) < (b) ? (a) : (b))
 10 #define max(a, b) ((a) > (b) ? (a) : (b))
 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 12 inline void swap(long long &a, long long &b)
 13 {
 14     long long tmp = a;a = b;b = tmp;
 15 }
 16 inline void read(long long &x)
 17 {
 18     x = 0;char ch = getchar(), c = ch;
 19     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 20     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 21     if(c == '-')x = -x;
 22 }
 23 
 24 const long long INF = 0x3f3f3f3f;
 25 const long long MAXN = 100000 + 10;
 26 
 27 long long n, num[MAXN], m;
 28 
 29 struct Node
 30 {
 31     long long sum, ma, l, r;
 32     Node(long long _sum, long long _ma, long long _l, long long _r){ma = _ma;sum = _sum;l = _l;r = _r;}
 33     Node(){sum = ma = l = r = 0;}
 34 }node[MAXN << 2];
 35 
 36 Node merge(Node &a, Node &b)
 37 {
 38     Node tmp;
 39     tmp.sum = a.sum + b.sum;
 40     tmp.l = a.l;tmp.r = b.r;
 41     tmp.ma = max(a.ma, b.ma);
 42     return tmp;
 43 }
 44 
 45 void build(long long o = 1, long long l = 1, long long r = n)
 46 {
 47     if(l == r)
 48     {
 49         node[o].l = node[o].r = l;
 50         node[o].sum = node[o].ma = num[l];
 51         return;
 52     }
 53     long long mid = (l + r) >> 1;
 54     build(o << 1, l, mid);
 55     build(o << 1 | 1, mid + 1, r);
 56     node[o] = merge(node[o << 1], node[o << 1 | 1]);
 57     return;
 58 }
 59 
 60 Node ask(long long ll, long long rr, long long o = 1)
 61 {
 62     if(ll <= node[o].l && rr >= node[o].r) return node[o];
 63     long long mid = (node[o].l + node[o].r) >> 1;
 64     Node a, b;
 65     if(mid >= ll) a = ask(ll, rr, o << 1);
 66     if(mid < rr) b = ask(ll, rr, o << 1 | 1);
 67     if(a.l == 0) return b;
 68     else if(b.l == 0) return a;
 69     else return merge(a, b);
 70 }
 71 
 72 void modify(long long ll, long long rr, long long o = 1)
 73 {
 74     if(node[o].l == node[o].r)
 75     {
 76         node[o].sum = node[o].ma = sqrt(node[o].sum);
 77         return;
 78     }
 79     if(node[o].ma <= 1) return;
 80     long long mid = (node[o].l + node[o].r) >> 1;
 81     if(mid >= ll) modify(ll, rr, o << 1);
 82     if(mid < rr) modify(ll, rr, o << 1 | 1);
 83     node[o] = merge(node[o << 1], node[o << 1 | 1]);
 84     return;
 85 }
 86 
 87 int main()
 88 {
 89     read(n);
 90     for(register long long i = 1;i <= n;++ i) read(num[i]);
 91     build();
 92     read(m);
 93     for(register long long i = 1;i <= m;++ i)
 94     {
 95         long long tmp1,tmp2,tmp3;
 96         read(tmp1), read(tmp2), read(tmp3);
 97         if(tmp2 > tmp3) swap(tmp2, tmp3);
 98         if(tmp1) 
 99         {
100             Node tmp = ask(tmp2, tmp3);
101             printf("%lld
", tmp.sum);
102         }
103         else modify(tmp2, tmp3);
104     }
105     return 0;
106 } 
BZOJ3038
原文地址:https://www.cnblogs.com/huibixiaoxing/p/8283302.html