HDU-4027-Can you answer these queries?线段树+区间根号+剪枝

传送门Can you answer these queries?

题意:

线段树,只是区间修改变成 把每个点的值开根号;

思路:

对$[X,Y]$的值开根号,由于最大为 $2^{63}$.可以观察到最多开根号7次即为1,则当根号次数大于等于7时,这段区间值为$R-L+1$,还有一点是L可能大于R。

以下来自鸟神:(真是强啊)

据这一性质,我们可以得到一种解决方案:对于修改,我们对于区间内的数不全为1的区间更新,直到遇到区间内的数全部为1的区间或者叶子结点为止。这样只要使用线段树,维护区间和的信息即可。 

 

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;

const int maxn = 100009;
ll a[maxn], sum[maxn * 4];
int n, m;

void pushup(int rt) {
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void buildup(int l, int r, int rt) {
    if (l == r) {
        sum[rt] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    buildup(l, mid, rt << 1);
    buildup(mid + 1, r, rt << 1 | 1);
    pushup(rt);
}
void update(int L, int R, int l, int r, int rt) {
    if (sum[rt] == r - l + 1) return; // 剪枝
    if (l == r) {
        sum[rt] = (int)sqrt(sum[rt]);
        return;
    }
    int mid = (l + r) >> 1;
    if (mid >= L) update(L, R, l, mid, rt << 1);
    if (R > mid) update(L, R, mid + 1, r, rt << 1 | 1);
    pushup(rt);
}
ll query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) {
        return sum[rt];
    }
    ll ans = 0;
    int mid = (l + r) >> 1;
    if (mid >= L) ans += query(L, R, l, mid, rt << 1);
    if (R > mid) ans += query(L, R, mid + 1, r, rt << 1 | 1);
    return ans;
}
int main() {
    int cnt = 0;
    while (~scanf("%d", &n)) {
        printf("Case #%d:\n", ++cnt);
        memset(a, 0, sizeof(a));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        buildup(1, n, 1);
        scanf("%d", &m);
        for (int i = 1; i <= m; i++) {
            int op, a, b;
            scanf("%d%d%d", &op, &a, &b);
            if (a > b) swap(a, b);
            if (op == 1) {
                ll ans = query(a, b, 1, n, 1);
                printf("%lld\n", ans);
            } else {
                update(a, b, 1, n, 1);
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 

posted @ 2018-03-04 21:41  ckxkexing  阅读(111)  评论(0编辑  收藏  举报