• HDU


    题目链接:Can you answer these queries?

    题意:维护一个序列,支持两种操作:(1)将区间[l,r]内的所有数开根号(向下取整),(2)求区间[l,r]内元素的和

    思路:和The Child and Sequence类似,对于操作(1),一个数最多开7次根号(向下取整)就会变为1,此时就不用再开根号了,所以我们用线段树维护区间和,如果一个区间和等于这个区间的长度,则表示这个区间内所有元素都为1,此时可以直接减枝,否则继续递归,直到叶子节点,然后开根号向下取整,其实也可以再维护一个区间最大值,如果最大值等于1,则可以直接减枝,对于操作(2),线段树区间查询区间和即可,注意可能有l>r,交换l,r即可

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 100010;
    
    struct node {
        int l, r;
        ll v;
    };
    
    int n, m, icas;
    node tr[4 * N];
    ll c[N];
    
    void build(int k, int l, int r)
    {
        tr[k].l = l, tr[k].r = r;
        if (l == r) {
            tr[k].v = c[l];
            return;
        }
        int mid = (l + r) / 2;
        build(2 * k, l, mid);
        build(2 * k + 1, mid + 1, r);
        tr[k].v = tr[2 * k].v + tr[2 * k + 1].v;
    }
    
    void update(int k, int a, int b)
    {
        if (tr[k].v == tr[k].r - tr[k].l + 1) return;
        if (tr[k].l == tr[k].r) {
            tr[k].v = sqrt(tr[k].v);
            return;
        }
        int mid = (tr[k].l + tr[k].r) / 2;
        if (a <= mid) update(2 * k, a, b);
        if (b > mid) update(2 * k + 1, a, b);
        tr[k].v = tr[2 * k].v + tr[2 * k + 1].v;
    }
    
    ll ask(int k, int a, int b)
    {
        if (tr[k].l >= a && tr[k].r <= b) return tr[k].v;
        int mid = (tr[k].l + tr[k].r) / 2;
        ll res = 0;
        if (a <= mid) res += ask(2 * k, a, b);
        if (b > mid) res += ask(2 * k + 1, a, b);
        return res;
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF) {
            for (int i = 1; i <= n; i++) scanf("%lld", &c[i]);
            build(1, 1, n);
            scanf("%d", &m);
            printf("Case #%d:
    ", ++icas);
            while (m--) {
                int op, a, b;
                scanf("%d%d%d", &op, &a, &b);
                if (a > b) swap(a, b);
                if (0 == op) update(1, a, b);
                else printf("%lld
    ", ask(1, a, b));
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    队列的顺序存储表示---数组实现
    栈的应用---用栈计算逆波兰表达式
    栈的应用--栈用作判断平衡符号,[()]对的,[(])错的
    栈ADT的数组实现
    栈ADT的链表实现
    链表的游标实现
    链表应用之基数排序
    多项式ADT的数组实现
    ListView13添加2
    计算器的简单编写,熟悉访问器,重载
  • 原文地址:https://www.cnblogs.com/zzzzzzy/p/12774040.html
Copyright © 2020-2023  润新知