• 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;
    }
  • 相关阅读:
    面试题:垂直居中几种方法
    零碎记忆--随机
    v-model 和 :model 的区别
    Vue--keep-alive 理解
    vue 中 $route 和 $router 的区别
    Vue + Element UI 实现权限管理系统 前端篇(十):动态加载菜单
    Vue + Element UI 实现权限管理系统 前端篇(九):接口格式定义
    Vue + Element UI 实现权限管理系统 前端篇(八):管理应用状态
    Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装
    [2020牛客暑期多校训练营(第十场)C Decrement on the Tree]
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12738448.html
Copyright © 2020-2023  润新知