12436 - Rip Van Winkle's Code

/********************
 * Author:fisty
 * Data:2014-11-5
 * uva12436
 * 线段树 成段更新
 * ****************/

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX_N 250000
typedef long long ll;

struct node{
        int l, r;
        bool flag;
        ll sum, add1, add2, valu, step;
        ll mid(){return l+(r - l) / 2;}
        ll len(){return r - l + 1;}
        void changeAB(ll a, ll b, ll k){
                add1 += a;
                add2 += b;
                step += k;
                sum += (a + b)*len()/2;
        }
        void changeC(ll a){
                valu = a; flag = 1;
                add1 = 0, add2 = 0;
                step = 0;
                sum = valu * len();
        }
}tree[250001 << 2];

struct segtree{
        void down(ll k){
                if(tree[k].flag){
                        tree[k<<1].changeC(tree[k].valu);
                        tree[k<<1|1].changeC(tree[k].valu);
                        tree[k].flag = 0;
                }
                if(tree[k].add1 || tree[k].add2 || tree[k].step){
                        ll add1 = tree[k].add1, add2 = tree[k].add2;
                        ll i = tree[k].step;
                        ll mid = add1 + i * (tree[k<<1].len()-1);
                        
                        tree[k<<1].changeAB(add1, mid, i);
                        tree[k<<1|1].changeAB(mid+i, add2, i);
                        tree[k].add1 = 0;
                        tree[k].add2 = 0;
                        tree[k].step = 0;
                }
        }
        void build(ll l, ll r, ll k){
                tree[k].l = l; tree[k].r = r;
                tree[k].add1 = 0; tree[k].add2 = 0;
                tree[k].sum = 0; tree[k].valu = 0;
                tree[k].step = 0;
                if(l != r){
                        ll  mid = tree[k].mid();
                        build(l, mid, k<<1);
                        build(mid+1 , r, k<<1|1);
                }
        }
        void update_AB(ll l, ll r, ll k, ll step){
                if(l <= tree[k].l && tree[k].r <= r){
                        //所能更新的区域是[tree[k].l, tree[k].r];
                        //但是需要更新的区域是[l,r];
                        //在l上加1,故在tree[k].l这点加上的是tree[k].l-l+1,在tree[k].r加上的是tree[k].r-l+1
                        int st, ed;
                        if(step >= 0){
                                st = tree[k].l - l + 1, ed = tree[k].r - l + 1;
                        }else{
                                st = r - tree[k].l + 1, ed = r - tree[k].r + 1;
                        }
                        tree[k].changeAB(st, ed, step);
                }else{
                        down(k);       
                        ll mid = tree[k].mid();
                        if(l <= mid) update_AB(l, r, k<<1, step);
                        if(r > mid) update_AB(l, r, k<<1|1, step);
                        
                        tree[k].sum = tree[k<<1].sum + tree[k<<1|1].sum;
                }
        }
        void update_C(ll l, ll r, ll k, ll valu){
                if(l <= tree[k].l && tree[k].r <= r){
                        tree[k].changeC(valu);
                }else{
                        down(k);
                        ll mid = tree[k].mid();
                        if(l <= mid) update_C(l, r, k<<1, valu);
                        if(r > mid) update_C(l ,r, k<<1|1, valu);
                        
                        tree[k].sum = tree[k<<1].sum + tree[k<<1|1].sum;
                }
        }
        ll query(ll l, ll r, ll k){
                if(l <=tree[k].l && tree[k].r <= r){
                        return tree[k].sum;
                }else{
                        down(k);
                        ll mid = tree[k].mid();
                        ll sum1 = 0, sum2 = 0;
                        if(l <= mid) sum1 = query(l, r, k<<1);
                        if(r > mid) sum2 = query(l , r, k<<1|1);
                        return sum1 + sum2;
                }
        }
}seg;
int main(){
        int t;
        while(scanf("%d", &t) != EOF){
                seg.build(1, MAX_N, 1);
                while(t--){
                        char str[10];
                        ll a, b;
                        scanf("%s", str);
                        if(str[0] == 'A'){
                                scanf("%lld%lld", &a, &b);
                                seg.update_AB(a, b, 1, 1);
                        }else if(str[0] == 'B'){
                                scanf("%lld%lld", &a, &b);
                                seg.update_AB(a, b, 1, -1);
                        }else if(str[0] == 'C'){
                                ll val;
                                scanf("%lld%lld%lld", &a, &b, &val);
                                seg.update_C(a, b, 1, val);
                        }else{
                                scanf("%lld%lld", &a, &b);
                                printf("%lld\n",seg.query(a, b, 1));
                        }

                }
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值