Can you answer these queries(线段树)

题意:

给出一个长为 $n$ 的数列 $a_1ldots a_n$ ,以及 $n$ 个操作,操作涉及区间开方,区间求和。

有多组测试数据。

Solution:

这道题可谓是真·暴力

区间操作,显然线段树。

我们发现不断开放下降很快,几次就搞定了,而0和1开方还是自己,所以我们在线段树的节点上记录一个标记flag确定一个区间内的数是不是都是0或1。

修改时如果发现一个当前区间已经全是0或1了回溯即可。

查询类似区间查询。其实就是一个单点修改+区间查询,不过每个点没修改的次数不会超过10。

有几个坑点:

1,它给你的区间有可能l>r

2,注意多组数据

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const long long MAX = 100010;
struct node{
    long long l, r;
    long long val;
    bool flag;
}t[MAX * 4];
long long n, s[MAX], q;
inline void build(long long l, long long r, long long id) {
    t[id].l = l, t[id].r = r;
    t[id].val = t[id].flag = 0;
    if (l == r) {
        t[id].val = s[l];
        return;
    }
    long long mid = (l + r) >> 1;
    build(l, mid, id * 2);
    build(mid + 1, r, id * 2 + 1);
    t[id].val = t[id * 2].val + t[id * 2 + 1].val;
}
inline void change(long long p, long long l, long long r) {
    long long _l = t[p].l, _r = t[p].r;
    if (t[p].flag) return;
    if (_l == _r) {
        t[p].val = sqrt(t[p].val);
        if (t[p].val <= 1) t[p].flag = 1;
        return;
    }
    long long mid = (_l + _r) >> 1;
    if (l <= mid) change(p * 2, l, r);
    if (r > mid) change(p * 2 + 1, l, r);
    t[p].val = t[p * 2].val + t[p * 2 + 1].val;
    if (t[p * 2].flag && t[p * 2 + 1].flag) t[p].flag = 1;
}
inline long long ask(long long p, long long l, long long r) {
    long long _l = t[p].l, _r = t[p].r;
    if (_l >= l && _r <= r) {
        return t[p].val;
    }
    long long mid = (_l + _r) >> 1;
    long long ret = 0;
    if (l <= mid) ret += ask(p * 2, l, r);
    if (r > mid) ret += ask(p * 2 + 1, l, r);
    return ret;
}
long long CRZzzz;
int main() {
    while (scanf("%lld", &n) != EOF) {
        CRZzzz++;
        printf("Case #%lld:
", CRZzzz);
        for (long long i = 1; i <= n; i++) {
            scanf("%lld", &s[i]);
        }
        build(1, n, 1);
        scanf("%lld", &q);
        while (q--) {
            long long opt, x, y;
            scanf("%lld%lld%lld", &opt, &x, &y);
            if (x > y) swap(x, y);
            if (opt == 1) {
                printf("%lld
", ask(1, x, y));
            } else {
                change(1, x, y);
            }
        }
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zcr-blog/p/12738448.html