zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    正则表达式
    小弟新从csdn搬迁到博客园,欢迎大家关注
    做完牛腩新闻发布系统之后的收获(牛腩总结)
    ValidateRequest="false" 无效
    sql server小技巧-自动添加时间与主键自增长
    css初接触
    Spark的Rpct模块的学习
    插入排序
    选择排序
    冒泡排序
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12738448.html
Copyright © 2011-2022 走看看