线段树 - HDU 4027 - Can you answer these queries?

  • 题目要求维护区间开方和,但由于

    \[tree[root] \neq sqrt(tree[leftroot] +tree[rightroot]) \]

    因此每一个更新操作都需要深入到叶子结点

  • 由于这么做复杂度太高,甚至弱于普通数组,因此考虑优化

    \[tree[root] = right - left+1 表明[left,right]区间全为1,再开方更新仍为1 \]

    因此再update操作时判断一下,进行剪枝

  • 本题坑点是输入数据不保证\(l < r\),需要特判替换,否则TLE

  • 注意开long long

#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
#define N 100000+5
typedef long long ll;

ll arr[N];
ll tree[N<<2];

void build_tree(int left,int right,int root){
    if(left == right){
        tree[root] = arr[left];
    }else{
        int mid = (left+right)>>1;
        int left_root = root<<1;
        int right_root = root<<1|1;
        build_tree(left,mid,left_root);
        build_tree(mid+1,right,right_root);
        tree[root] = tree[left_root]+tree[right_root];
    }
}

void update(int left,int right,int root,int update_left,int update_right){
    if(update_left > right || update_right < left || tree[root] == right-left+1){
        return;
    }else{
        if(left == right){
            tree[root] = (int)sqrt(tree[root]);
        }else{
            int mid = (left+right)>>1;
            int left_root = root<<1;
            int right_root = root<<1|1;
            update(left,mid,left_root,update_left,update_right);
            update(mid+1,right,right_root,update_left,update_right);
            tree[root] = tree[left_root] + tree[right_root];
        }
    }
}

ll query(int left,int right,int root,int query_left,int query_right){
    if(query_left <= left && query_right >= right){
        return tree[root];
    }else{
        int mid = (left+right)>>1;
        int left_root = root<<1;
        int right_root = root<<1|1;
        ll ans = 0;
        if(query_left <= mid){
            ans += query(left,mid,left_root,query_left,query_right);
        }
        if(query_right > mid){
            ans += query(mid+1,right,right_root,query_left,query_right);
        }
        return ans;
    }
}

int main(){
    int n;
    int g = 1;
    while(scanf("%d",&n) != EOF){
        printf("Case #%d:\n",g++);
        for(int i = 1; i <= n; i++){
            scanf("%lld",&arr[i]);
        }
        build_tree(1,n,1);
        int q;
        int a,b,c;
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d",&a,&b,&c);
            if(b > c){
                int temp = c;
                c = b;
                b = temp;
            }
            if(a == 0){
                update(1,n,1,b,c);
            }else{
                printf("%lld\n",query(1,n,1,b,c));
            }
        }
        putchar('\n');
    }
    system("pause");
    return 0;
}

posted @ 2020-10-29 09:40  popozyl  阅读(50)  评论(0编辑  收藏  举报