码迷,mamicode.com
首页 > 其他好文 > 详细

uva 12436(区间更新)

时间:2015-08-20 20:57:57      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

题意:有n个操作,操作种类有A a b表示把区间[a,b]的值依次加1 2 … b-a+1,操作B a b表示把区间[a,b]的值依次加b-a+1… 2 1,操作C a b x表示把区间[a,b]的值全部替换为x,操作S a b要求输出区间[a,b]里的所有数字的和。
题解:A和B操作都是把区间内加上一个等差数列,所以要用线段树维护每个区间所要加的等差数列的首项还有公差,注意操作C里的x还可以取负值和0,所以需要再添加一个标记数组flag。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 250005;
ll tree[N << 2], setv[N << 2], a0[N << 2], d[N << 2];
int flag[N << 2];
char op[5];

void pushdown(ll k, ll left, ll right) {
    if (flag[k]) {
        ll len = right - left + 1;
        setv[k * 2] = setv[k * 2 + 1] = setv[k];
        flag[k * 2] = flag[k * 2 + 1] = flag[k];
        tree[k * 2] = setv[k] * (len - len / 2);
        tree[k * 2 + 1] = setv[k] * (len / 2);
        d[k * 2] = d[k * 2 + 1] = a0[k * 2] = a0[k * 2 + 1] = 0;
        flag[k] = 0;
    }
    if (a0[k] || d[k])  {
        d[k * 2] += d[k];
        d[k * 2 + 1] += d[k];
        a0[k * 2] += a0[k];
        ll mid = (right + left) / 2;
        ll a1 = a0[k] + d[k] * (mid - left + 1);
        ll nl = mid - left + 1, nr = right - mid;
        tree[k * 2] += a0[k] * nl + nl * (nl - 1) / 2 * d[k];
        a0[k * 2 + 1] += a1;
        tree[k * 2 + 1] += a1 * nr + nr * (nr - 1) / 2 * d[k];  
        a0[k] = d[k] = 0;
    }
}

void pushup(ll k) {
    tree[k] = tree[k * 2] + tree[k * 2 + 1];
}

void modify(ll k, ll left, ll right, ll l, ll r, ll dd) {
    if (l <= left && right <= r) {
        ll st;
        if (dd >= 0)
            st = left - l + 1;
        else
            st = r - left + 1;
        a0[k] += st, d[k] += dd;
        ll n = right - left + 1;
        tree[k] += st * n + n * (n - 1) / 2 * dd;
        return;
    }
    pushdown(k, left, right);
    int mid = (left + right) / 2;
    if (l <= mid)
        modify(k * 2, left, mid, l, r, dd);
    if (r > mid)
        modify(k * 2 + 1, mid + 1, right, l, r, dd);
    pushup(k);
}

void modify2(ll k, ll left, ll right, ll l, ll r, ll x) {
    if (l <= left && right <= r) {
        flag[k] = 1;
        setv[k] = x;
        tree[k] = x * (right - left + 1);
        a0[k] = d[k] = 0;
        return;
    }
    pushdown(k, left, right);
    ll mid = (left + right) / 2;
    if (l <= mid)
        modify2(k * 2, left, mid, l, r, x);
    if (r > mid)
        modify2(k * 2 + 1, mid + 1, right, l, r, x);
    pushup(k);
}

ll query(ll k, ll left, ll right, ll l, ll r) {
    if (l <= left && right <= r)
        return tree[k];
    pushdown(k, left, right);
    ll mid = (left + right) / 2, res = 0;
    if (l <= mid)
        res += query(k * 2, left, mid, l, r);
    if (r > mid)
        res += query(k * 2 + 1, mid + 1, right, l, r);
    pushup(k);
    return res;
}

int main() {
    int t;
    ll x, l, r;
    scanf("%d", &t);
    memset(tree, 0, sizeof(tree));
    memset(a0, 0, sizeof(a0));
    memset(d, 0, sizeof(d));
    memset(flag, 0, sizeof(flag));
    while (t--) {
        scanf("%s%lld%lld", op, &l, &r);
        if (op[0] == ‘A‘)
            modify(1, 1, N - 1, l, r, 1);
        else if (op[0] == ‘B‘)
            modify(1, 1, N - 1, l, r, -1);
        else if (op[0] == ‘C‘) {
            scanf("%lld", &x);
            modify2(1, 1, N - 1, l, r, x);
        }
        else
            printf("%lld\n", query(1, 1, N - 1, l, r));
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

uva 12436(区间更新)

标签:

原文地址:http://blog.csdn.net/hyczms/article/details/47813307

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!