[BZOJ3038]上帝造题的七分钟2
3038: 上帝造题的七分钟2
Time Limit: 3 Sec Memory Limit: 128 MB Submit: 1532 Solved: 657 [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
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
7
6
HINT
1:对于100%的数据,1<=n<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。
2:数据不保证L<=R 若L>R,请自行交换L,R,谢谢!
考虑到开方数字下降得非常快,并且除了开方没有其它修改,那么每次开方暴力开就行了,维护一个Max和sum,当然区间最大值等于$1$了就没必要往下走了,那么询问是$O(log(n))$的,修改是均摊$O(1)$的(听说还能用并查集做??)
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; char buf[10000000], *ptr = buf - 1; inline ll readll(){ ll n = 0; char ch = *++ptr; while(ch < '0' || ch > '9') ch = *++ptr; while(ch <= '9' && ch >= '0'){ n = (n << 1) + (n << 3) + ch - '0'; ch = *++ptr; } return n; } inline int readint(){ int n = 0; char ch = *++ptr; while(ch < '0' || ch > '9') ch = *++ptr; while(ch <= '9' && ch >= '0'){ n = (n << 1) + (n << 3) + ch - '0'; ch = *++ptr; } return n; } const int maxn = 100000 + 10; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 ll Max[maxn << 2], sum[maxn << 2]; void inline PushUp(int rt){ Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]); sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void Build(int l, int r, int rt){ if(l == r) sum[rt] = Max[rt] = readll(); else{ int mid = l + r >> 1; Build(lson); Build(rson); PushUp(rt); } } int ql, qr; void Update(int l, int r, int rt){ if(l == r){ sum[rt] = sqrt(sum[rt]); Max[rt] = sqrt(Max[rt]); } else{ int mid = l + r >> 1; if(ql <= mid && Max[rt << 1] > 1) Update(lson); if(qr > mid && Max[rt << 1 | 1] > 1) Update(rson); PushUp(rt); } } ll Query(int l, int r, int rt){ if(ql <= l && r <= qr) return sum[rt]; else{ int mid = l + r >> 1; ll ret = 0; if(ql <= mid) ret += Query(lson); if(qr > mid) ret += Query(rson); return ret; } } int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); int n = readint(); Build(1, n, 1); int m = readint(), opt; for(int i = 1; i <= m; i++){ opt = readint(); ql = readint(); qr = readint(); if(ql > qr) swap(ql, qr); if(opt == 0) Update(1, n, 1); else printf("%lld\n", Query(1, n, 1)); } return 0; }