LOJ #6281. 数列分块入门 5

版权声明:欢迎转载 https://blog.csdn.net/yandaoqiusheng/article/details/88607116

题目链接:传送门

区间求和,区间开方

显然一个数开不了几次就变成1了
所以再维护一个块内是不是都变成了1
到时候就可以少更新许多

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 1000010
#define B 2010

using namespace std;
typedef long long ll;
int n, bl[A], sq[A], s[A], vis[A], m, a, b, c, opt;
void sqr(int a, int b, int c) {
    if (!vis[bl[a]]) {
        for (int i = a; i <= min(bl[a] * m, b); i++) s[bl[a]] -= sq[i], sq[i] = sqrt(sq[i]), s[bl[a]] += sq[i];
        vis[bl[a]] = 1;
        for (int i = (bl[a] - 1) * m + 1; i <= bl[a] * m; i++)
            if (sq[i] > 1) {
                vis[bl[a]] = 0;
                break;
            }
    }
    if (bl[a] != bl[b] and !vis[bl[b]]) {
        for (int i = (bl[b] - 1) * m + 1; i <= b; i++) s[bl[b]] -= sq[i], sq[i] = sqrt(sq[i]), s[bl[b]] += sq[i];
        vis[bl[b]] = 1;
        for (int i = (bl[b] - 1) * m + 1; i <= bl[b] * m; i++)
            if (sq[i] > 1) {
                vis[bl[b]] = 0;
                break;
            }
    }
    for (int i = bl[a] + 1; i <= bl[b] - 1; i++) {
        if (vis[i]) continue;
        vis[i] = 1; s[i] = 0;
        for (int j = (i - 1) * m + 1; j <= i * m; j++) {
            sq[j] = sqrt(sq[j]);
            s[i] += sq[j];
            if (sq[j] > 1) vis[i] = 0;
        }
    }
}
ll ask(int a, int b, ll ans = 0) {
    for (int i = a; i <= min(bl[a] * m, b); i++) ans += sq[i];
    if (bl[a] != bl[b])
        for (int i = (bl[b] - 1) * m + 1; i <= b; i++) ans += sq[i];
    for (int i = bl[a] + 1; i <= bl[b] - 1; i++) ans += s[i];
    return ans;
}

int main(int argc, char const *argv[]) {
    scanf("%d", &n); m = sqrt(n);
    for (int i = 1; i <= n; i++) bl[i] = (i - 1) / m + 1;
    for (int i = 1; i <= n; i++) scanf("%d", &sq[i]), s[bl[i]] += sq[i];
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &opt, &a, &b, &c);
        if (!opt) sqr(a, b, c);
        else printf("%lld\n", ask(a, b));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yandaoqiusheng/article/details/88607116