acmoj - 数蘑菇线段树区间更新

来源:互联网 发布:花王染发剂颜色知乎 编辑:程序博客网 时间:2024/05/04 12:28

数蘑菇


题目描述

某土豪有许多种蘑菇的房子(编号从1到n,n<=10000),每个房子开始时有个蘑菇,大小在2到1000之间,每当洒脱的土豪给他们浇水时,这些蘑菇就会变成原来的平方倍大,比如一个大小为2的蘑菇在土豪浇过水之后就会变成4这么大,但是因为土豪住在帝都,每个房子只有1000平方米这么大,所以每个蘑菇在长到1000之后就不会再长大了(比如对于一个大小为50的蘑菇浇水,它也只能长大到1000),土豪每天喜欢骑着自行车(乡下人羡慕城里人开车溜达,城里的土豪却骑着自行车,你们城里人真会玩)给一连串的房子里的蘑菇浇水,从l到r,然后土豪又经常要查询某些房间的蘑菇一共有多少了,好联系卖家,聪明的你,能帮土豪这个忙吗?搞不好土豪一高兴随便送套房子给你呢!


输入描述

输入首先是一个T,表示一共有T组数据

下一行是一个n,代表土豪有几间房子

下一行是n个整数数,代表从1到n每个房间开始蘑菇的大小(<=1000)

下一行是一个整数k(1<=k<=10000),表示土豪浇水和数蘑菇的次数,

后面跟着k行,每行三个整数q,l,r(1<=l<=r<=10000)

q表示土豪的操作,

q为0的时候表示土豪给l到r这些房间里的蘑菇浇水,

q为1的时候表示土豪想要知道l到到r这些房间里的蘑菇总大小


输出描述

对于第n组数据首先输出一行"Case #n:",然后对于每次询问输出一个答案,每个答案占一行


输入样例

1102 3 4 5 6 7 8 9 10 1130 1 101 1 101 1 5

输出样例

Case #1:50590
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 10000 + 5;int n, T, m;int sum[maxn << 2],col[maxn << 2];bool isupd[maxn << 2];//记录着他的子区间是否有要更新的void inline pushup(int rt) {    sum[rt] = sum[rt << 1] + sum[rt << 1|1];    if(rt & 1)        isupd[(rt + 1) / 2] = isupd[rt];//如果子有要更新的,就要标记父亲节点,告诉他子节点有更新    else        isupd[rt / 2] = isupd[rt];}void inline pushdown(int rt) {    if(col[rt]) {        col[rt << 1] += col[rt];        col[rt << 1|1] += col[rt];        col[rt] = 0;    }    isupd[rt << 1] = isupd[rt];    isupd[rt << 1|1] = isupd[rt];}void build(int rt, int l, int r) {    col[rt] = 0;    isupd[rt] = 0;    if(l == r) {        scanf("%d", &sum[rt]);        return;    }    int mid = (l + r) >> 1;    build(rt << 1, l, mid);    build(rt << 1|1, mid + 1, r);    pushup(rt);}void update(int L, int R, int c, int rt, int l, int r) {    if(L <= l && r <= R) {        col[rt] += c;        isupd[rt] = 1;        return;    }    pushdown(rt);    int mid = (l + r) >> 1;    if(L <= mid) update(L, R, c, rt << 1, l, mid);    if(R > mid) update(L, R, c,rt << 1|1, mid + 1, r);    pushup(rt);}int query(int L, int R, int rt, int l, int r) {    if(l == r) {        if(sum[rt] == 1000)return sum[rt];//必须剪枝,否则超时        if(isupd[rt]) {            for(int i = 0; i < col[rt]; i ++) {                sum[rt] = sum[rt] * sum[rt];                if(sum[rt] >= 1000) sum[rt] = 1000;            }            col[rt] = 0;            isupd[rt] = 0;        }        return sum[rt];    }    if(L <= l && r <= R) {        int res = sum[rt];        if(sum[rt] == 1000 * (r - l + 1))return sum[rt];//必须剪枝,否则超时        if(isupd[rt]) {//如果子节点有更新,那么他的值就要重新通过求和来确定            res = 0;            int mid = (l + r) >> 1;            pushdown(rt);            res += query(l, r, rt << 1 , l, mid);            res += query(l, r, rt << 1|1, mid + 1, r);            isupd[rt] = 0;        }        return sum[rt] = res;    }    int mid = (l + r) >> 1;    int res = 0;    if(L <= mid)res += query(L, R, rt << 1, l, mid);    if(R > mid) res += query(L, R, rt << 1|1, mid + 1, r);    pushup(rt);    return res;}int main() {    int q, l, r, tt = 1;    //freopen("D://imput.txt","r",stdin);    scanf("%d", &T);    while(T --) {        scanf("%d", &n);        build(1, 1, n);        scanf("%d", &m);        printf("Case #%d:\n",tt ++);        for(int i = 0; i < m; i ++) {            scanf("%d%d%d", &q, &l, &r);            if(q) {                printf("%d\n",query(l, r, 1, 1, n));            } else {                update(l, r, 1, 1, 1, n);            }        }    }    return 0;}


1 1
原创粉丝点击