深刻理解到读题的重要性。
0 x y 表示对x和y之间的值进行开根号,向下取整。
1 x y 为求和操作,N属于[1, 1e5]。
因为对元素开根(向下取整),所以每个元素开不了几次,比如2^63次方,log一下最多开7次而已。而1怎么开方都是1,于是如果某一段被开到全都为1,满足g[rt]=r-l+1,那么这段不必更新,以此来节约时间。
还有就是其实是x,y之间的飞船进行开根处理,并没有说x<=y...所以读入后要检查一下。
#include <stdio.h> #include <iostream> #include <math.h> using namespace std; #define ll long long #define FOR(i,a,b) for(int i=(a);i<=(b);++i) const int maxN=1e5+5; int N, M, K, T; #define lson l,m,rt*2 #define rson m+1,r,rt*2+1 ll g[maxN<<2]; void push_up(int rt) {g[rt] = g[rt * 2] + g[rt * 2 + 1];} void build(int l, int r, int rt) { if (l == r) { scanf("%lld", &g[rt]); return; } int m = (l + r) / 2; build(lson); build(rson); push_up(rt); } void update(int L, int R, int l, int r, int rt) { if (g[rt] == r - l + 1) return; if (l == r) { g[rt] = sqrt(g[rt]);; return; } int m = (l + r) / 2; if (L <= m) update(L, R, lson); if (R > m) update(L, R, rson); push_up(rt); } ll query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return g[rt]; } int m = (l + r) / 2; ll ans = 0; if (L <= m) ans += query(L, R, lson); if (R > m) ans += query(L, R, rson); return ans; } int main () { int cas = 1; while (~scanf("%d", &N)) { build(1, N, 1); scanf("%d", &M); printf("Case #%d: ", cas++); int t, a, b; FOR(i, 1, M) { scanf("%d%d%d", &t, &a, &b); if (a > b) swap(a, b); if (t == 0) update(a, b, 1, N, 1); else printf("%lld ", query(a, b, 1, N, 1)); } puts(""); } return 0; }