【bzoj3038】上帝造题的七分钟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,谢谢!
*来源:
Poetize4
*题解:
线段树。区间开根号就暴力递归进去改,对于都是1的区间就不改。由于只有区间开根的修改操作所以复杂度是有保证的。
*代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif
#define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
R char ch; R int cnt = 0; R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? minus = 1 : cnt = ch - '0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus ? -cnt : cnt;
}
inline long long FastIn2()
{
R char ch; R long long cnt = 0; R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? minus = 1 : cnt = ch - '0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus ? -cnt : cnt;
}
#define maxn 100010
long long Tr[1 << 20], a[maxn];
bool is_one[1 << 20];
int ql, qr;
#define ls o << 1
#define rs o << 1 | 1
#define update(o) Tr[o] = Tr[ls] + Tr[rs], is_one[o] = is_one[ls] && is_one[rs];
void Build(R int o, R int l, R int r)
{
if (l == r)
{
Tr[o] = a[l];
is_one[o] = a[l] == 1;
return ;
}
R int mid = l + r >> 1;
Build(ls, l, mid);
Build(rs, mid + 1, r);
update(o);
}
long long Query(R int o, R int l, R int r)
{
if (ql <= l && r <= qr) return Tr[o];
R int mid = l + r >> 1; R long long ans = 0;
if (ql <= mid) ans += Query(ls, l, mid);
if (qr > mid) ans += Query(rs, mid + 1, r);
return ans;
}
void Modify(R int o, R int l, R int r)
{
if (l == r) {Tr[o] = floor(sqrt(Tr[o])); is_one[o] = Tr[o] == 1;return ;}
R int mid = l + r >> 1;
if (ql <= mid && !is_one[ls]) Modify(ls, l, mid);
if (qr > mid && !is_one[rs]) Modify(rs, mid + 1, r);
update(o);
}
int main()
{
// setfile();
R int n = FastIn();
for (R int i = 1; i <= n; ++i) a[i] = FastIn2();
Build(1, 1, n);
for (R int q = FastIn(); q; --q)
{
R int opt = FastIn();
ql = FastIn(), qr = FastIn();
if (ql > qr) std::swap(ql, qr);
if (opt)
printf("%lld\n", Query(1, 1, n));
else
Modify(1, 1, n);
}
return 0;
}
/*
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
*/