链接:https://vjudge.net/problem/HDU-4027#author=0
题意:
给n个数,两种操作,一种对将区间内l数全部变成原来的平方根,向下取整。
一种求区间的和。
思路:
线段数,区间更新,当区间内所有数都为1时不向下更新,即segment[root] == (r - l + 1)时。
代码:
#include <iostream> #include <memory.h> #include <vector> #include <map> #include <algorithm> #include <cstdio> #include <math.h> using namespace std; typedef long long LL; const int MAXN = 1e5 + 10; LL segment[MAXN * 4]; LL a[MAXN]; int n, m; int op, l, r; void Init() { memset(segment, 0, sizeof(segment)); memset(a, 0, sizeof(a)); } void Build_Tree(int root, int l, int r) { if (l == r) { segment[root] = a[l]; return; } int mid = (l + r) / 2; Build_Tree(root << 1, l, mid); Build_Tree(root << 1 | 1, mid + 1, r); segment[root] = segment[root << 1] + segment[root << 1 | 1]; } void Update_Tree(int root, int l, int r, int ql, int qr) { if (ql > r || l > qr) return; if (segment[root] == (r - l + 1)) return; if (l == r) { segment[root] = sqrt(segment[root]); return; } int mid = (l + r) / 2; Update_Tree(root << 1, l, mid, ql, qr); Update_Tree(root << 1 | 1, mid + 1, r, ql, qr); segment[root] = segment[root << 1] + segment[root << 1 | 1]; } LL Query(int root, int l, int r, int ql, int qr) { if (ql > r || l > qr) return 0; if (ql <= l && r <= qr) return segment[root]; int mid = (l + r) / 2; LL res = 0; res += Query(root << 1, l, mid, ql, qr); res += Query(root << 1 | 1, mid + 1, r, ql, qr); return res; } int main() { int cnt = 0; while (~scanf("%d", &n)) { printf("Case #%d: ", ++cnt); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); scanf("%d", &m); Build_Tree(1, 1, n); while (m--) { scanf("%d%d%d", &op, &l, &r); if (l > r) swap(l, r); if (op == 0) Update_Tree(1, 1, n, l, r); else printf("%lld ", Query(1, 1, n, l, r)); } printf(" "); } return 0; }