1. 程式人生 > 實用技巧 >線段樹 - HDU 4027 - Can you answer these queries?

線段樹 - 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;
}