BZOJ3211 花神游历各国 线段树

题意:给定一个数列,维护:1、区间求和  2、区间开根号

题解:

线段树,唯一的优化就是如果某区间的和为0和1,就不再向下进行更新。(注意long long)

另外动态开内存真的好慢- -,我的机子上3s(注意是s)才跑完一次,评测机T的不要不要的。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

typedef struct NODE{
    NODE *lchild,*rchild;
    int L,R;
    long long sum;
    bool lazy;
    NODE(){}
}*TREE;
TREE root;
int n,m;

void Pushup(TREE & node){
    node->sum=node->lchild->sum+node->rchild->sum;
    node->lazy=node->lchild->lazy&node->rchild->lazy;
}

void Build(TREE & root,int l,int r){
    root=new NODE;
    root->L=l,root->R=r,root->sum=root->lazy=0;

    if(l==r){
        scanf("%lld",&root->sum);
        if(root->sum==0 || root->sum==1) root->lazy=1;
        return;
    }

    int m=(l+r)>>1;
    Build(root->lchild,l,m);
    Build(root->rchild,m+1,r);

    Pushup(root);
}

long long Query(TREE & root,int l,int r){
    if(l<=root->L && r>=root->R) return root->sum;

    int m=(root->L+root->R)>>1;
    long long tmp=0;
    if(l<=m) tmp+=Query(root->lchild,l,r);
    if(r>=m+1) tmp+=Query(root->rchild,l,r);

    return tmp;
}

void Update(TREE & root,int l,int r){
    if(root->lazy) return;

    if(root->L==root->R){
        root->sum=(long long)sqrt(root->sum);
        if(root->sum==1 || root->sum==0) root->lazy=1;
        return;
    }

    int m=(root->L+root->R)>>1;
    if(l<=m) Update(root->lchild,l,r);
    if(r>m) Update(root->rchild,l,r);

    Pushup(root);
}

void Delete(TREE & root){
    if(root->L==root->R){
        delete root;
        return;
    }

    Delete(root->lchild);
    Delete(root->rchild);

    delete root;
}

void Visit(TREE & root){
    if(root->L==root->R){
        cout << root->sum << " ";
        return;
    }

    Visit(root->lchild);
    Visit(root->rchild);

    cout << root->sum << " ";
}

int main(){
    cin >> n;
    Build(root,1,n);

    cin >> m;
    int x,l,r;
    while(m--){
        cin >> x >> l >> r;
        l=min(l,r),r=max(l,r);

        if(x==1) cout << Query(root,l,r) << endl;
        if(x==2) Update(root,l,r);
    }

    Delete(root);

    return 0;
}
View Code

 

posted @ 2017-02-28 01:12  WDZRMPCBIT  阅读(148)  评论(0编辑  收藏  举报