zoukankan      html  css  js  c++  java
  • [Data Structure][线段树]BZOJ3211 花神游历各国

    BZOJ3211: 花神游历各国

    题意

    给定$n$个数,$m$个操作,一种查询区间内所有数的和,一种将区间内所有数开根后取整。输出所有查询的结果。

    题解

    线段树。唯一的$trick$是由于这$n$个数的范围是$[0,10^9]$,最多开$5$次根就会达到$0$,于是我们开一个$cnt$数组记录一段区间是否需要继续开根即可。

    代码

    #include <bits/stdc++.h>
    #define lson root << 1
    #define rson root << 1 | 1
    #define ltree lson, l, m
    #define rtree rson, m + 1, r
    using namespace std;
    typedef long long ll;
    const int N = 1e5+9;
    
    ll data[N], sum[4 * N], cnt[4 * N];
    
    inline int read() {
        int s = 1, x = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
        return s * x;
    }
    
    inline void build(int root, int l, int r) {
        if (l == r) {
            sum[root] = data[l], cnt[root] = (data[l] <= 1); return;
        }
        int m = (l + r) >> 1;
        build(ltree);
        build(rtree);
        sum[root] = sum[lson] + sum[rson];
        cnt[root] = cnt[lson] + cnt[rson];
    }
    
    inline ll query(int root, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr) return sum[root];
        int m = (l + r) >> 1;
        ll ret = 0;
        if (ql <= m) ret += query(ltree, ql, qr);
        if (qr > m) ret += query(rtree, ql, qr);
        return ret;
    }
    
    inline void update(int root, int l, int r, int ql, int qr) {
        if (cnt[root] == r - l + 1) return;
        if (l == r) {
            sum[root] = (ll) sqrt(sum[root]), cnt[root] = (sum[root] <= 1); return;
        }
        int m = (l + r) >> 1;
        if (ql <= m) update(ltree, ql, qr);
        if (qr > m) update(rtree, ql, qr);
        sum[root] = sum[lson] + sum[rson];
        cnt[root] = cnt[lson] + cnt[rson];
    }
    
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) data[i] = read();
        build(1, 1, n);
    
        int m = read();
        for (int i = 1; i <= m; i++) {
            int x = read(), l = read(), r = read();
            if (x == 1) printf("%lld\n", query(1, 1, n, l, r));
            if (x == 2) update(1, 1, n, l, r);
        }
        return 0;
    }
    
  • 相关阅读:
    线程带参数操作
    静态页面不识别include
    当网站遭遇DDOS攻击的解决方案及展望
    带进度条上传控件
    用js实现了表格数据管理的以下几个功能:
    怎么面试一个人
    map的使用
    在Axapta中实现trim函数
    Axapta财务过账分析(一)
    在Axapta中实现split函数
  • 原文地址:https://www.cnblogs.com/jstztzy/p/7399827.html
Copyright © 2011-2022 走看看