关闭

hdu 4027 Can you answer these queries? 线段树

标签: 线段树
188人阅读 评论(0) 收藏 举报

题意:有一个长度为n的序列,有两种操作,第一种把在区间[x,y]之内的所有数,变成它的平方根。第二种操作,查询这个区间内的和。

思路:开始想了怎么区间更新,并没有想法,然后一想,卧槽,每个节点最多只会更新8次左右呀,直接更新就好了,于是暴力更新。统计1的个数,区间为1就不更新了。

坑点:x可能会大于y

http://acm.hdu.edu.cn/showproblem.php?pid=4027

#include <cstdio>
#include <cmath>
#include <iostream>

using namespace std;

const int MAXN = 1e5+5;

struct Node {
    int x,y;
    int k; //区间内1的个数;
    long long sum; //区间内总和;
}t[MAXN<<2];

int n,m;

void Push_Up(int rt) {
    t[rt].sum = t[rt<<1].sum + t[rt<<1|1].sum;
    t[rt].k = t[rt<<1].k + t[rt<<1|1].k;
}

void Build(int x,int y,int rt) {
    t[rt].x = x; t[rt].y = y;
    if(t[rt].x == t[rt].y) {
        scanf("%I64d",&t[rt].sum);

        if(t[rt].sum == 1)t[rt].k = 1;
        else t[rt].k = 0;

        return ;
    }
    int mid = (x + y) >> 1;
    Build(x,mid,rt<<1);
    Build(mid+1,y,rt<<1|1);
    Push_Up(rt);
}

void Update(int rt,int left,int right) {
    if((t[rt].y -t[rt].x + 1) == t[rt].k) return ;
    if(t[rt].y == t[rt].x) {
        t[rt].sum = (long long)sqrt(t[rt].sum);
        if(t[rt].sum == 1) {
            t[rt].k = 1;
        }
        return ;
    }
    int mid = (t[rt].x + t[rt].y) >> 1;
    if(mid >= left) {
        Update(rt<<1,left,right);
    }
    if(mid < right) {
        Update(rt<<1|1,left,right);
    }
    Push_Up(rt);
}

long long Query(int rt,int left,int right) {
    if(t[rt].x >= left && t[rt].y <= right) {
        return t[rt].sum;
    }
    long long ans = 0;
    int mid = (t[rt].x + t[rt].y) >> 1;
    if(mid >= left) {
        ans += Query(rt<<1,left,right);
    }
    if(mid < right) {
        ans += Query(rt<<1|1,left,right);
    }
    return ans;
}

void input() {
    Build(1,n,1);
    scanf("%d",&m);
    int ok,left,right;
    for(int i = 1 ; i <= m ; i ++) {
        scanf("%d %d %d",&ok,&left,&right);
        if(left > right) swap(left,right);
        if(ok == 0) {
            Update(1,left,right);
        }
        else {
            printf("%I64d\n",Query(1,left,right));
        }
    }
}

void solve() {

}

int main(void) {
    //freopen("a.in","r",stdin);
    int CASENUM = 1;
    while(~scanf("%d",&n)) {
        printf("Case #%d:\n",CASENUM++);
        input();
        solve();
        puts("");
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:59683次
    • 积分:3594
    • 等级:
    • 排名:第9135名
    • 原创:315篇
    • 转载:3篇
    • 译文:0篇
    • 评论:4条
    文章分类
    最新评论