3038: 上帝造题的七分钟2
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 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
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
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\n", tmp.sum); 102 } 103 else modify(tmp2, tmp3); 104 } 105 return 0; 106 }