UVA 12436 Rip Van Winkle's Code(线段树区间更新)

来源:互联网 发布:刘备 爱哭 知乎 编辑:程序博客网 时间:2024/06/06 14:19

题意:

对于长度为250000的区间,给了你四种操作:
操作A,从st到ed这段区间内的数,分别加上1,2,…,st-ed+1。
操作B,从st到ed这段区间内的数,分别加上,st-ed+1,st-ed,…,1。
操作C,将st到ed这段区间内的数赋值成x。
操作S,查询st到ed的这段区间内的数的总和。

解析:

因为操作A和操作B都是操作的实际上都是等差数列,所以可以一起考虑。
对于操作AB,在线段树的结点中记录了这个区间的首项a1,同时记录了这段区间内的公差d。
对于操作C,在线段树的结点内,用一个cover表示当前区间内的数是否全部相同,并且还用一个val表示如果在区间里的数完全相同的时候,即cover=1时,这个数是多少。

容易得到,等差数列相加还是等差数列,所以可以对一个区间进行多次的AB操作。
对于C操作,因为强制将区间内的赋值成x,所以之前的AB操作全部失效,即这时候应该把表示AB操作的几个变量,a1和d全部赋值为零。
当向子区间传递记录的值的时候,应该优先C操作的标记,因为当操作AB和操作C的标记同时存在的时候,一定是发生在先进行了操作C,再进行了操作AB。

my code

#include <cstdio>#include <cstring>#include <algorithm>#define ls (o<<1)#define rs (o<<1|1)#define lson ls, L, M #define rson rs, M+1, Rusing namespace std;typedef long long ll;const int N = 250001;struct Node {    int L, R;    ll a1, d, val, sum;    bool cover;    Node() { a1 = d = val = sum = cover = 0;}    ll length() { return R - L + 1; }} node[N<<2];void pushUp(int o) {    node[o].sum = node[ls].sum + node[rs].sum;}void pushDown(int o) {    if(node[o].cover) {        node[ls].cover = node[rs].cover = true;        node[ls].val = node[rs].val = node[o].val;        node[ls].sum = node[ls].length() * node[o].val;        node[rs].sum = node[rs].length() * node[o].val;        node[ls].a1 = node[ls].d = node[rs].a1 = node[rs].d = 0;        node[o].val = node[o].cover = 0;    }    if(node[o].a1 || node[o].d) {        ll d = node[o].d;        ll len1 = node[ls].length(), len2 = node[rs].length();        ll a1 = node[o].a1, a2 = a1 + len1 * d;        node[ls].a1 += a1;        node[ls].d += d;        node[ls].sum += a1 * len1 + len1 * (len1-1)/2 * d;        node[rs].a1 += a2;        node[rs].d += d;        node[rs].sum += a2 * len2 + len2 * (len2-1)/2 * d;        node[o].a1 = node[o].d = 0;    }}void build(int o, int L, int R) {    node[o] = Node();    node[o].L = L, node[o].R = R;    if(L == R) return ;    int M = (L + R)/2;    build(lson);    build(rson);    pushUp(o);}void modify(int o, int L, int R, int ql, int qr, ll d) {    if(ql <= L && R <= qr) {        ll a1 = (d == 1) ? (L - ql + 1) : (qr - L + 1);        ll n = node[o].length();        node[o].a1 += a1;        node[o].d += d;        node[o].sum += a1 * n + n * (n-1)/2 * d;        return ;    }    pushDown(o);    int M = (L + R)/2;    if(ql <= M) modify(lson, ql, qr, d);    if(qr > M) modify(rson, ql, qr, d);    pushUp(o);}void setValue(int o, int L, int R, int ql, int qr, ll val) {    if(ql <= L && R <= qr) {        node[o].sum = node[o].length() * val;        node[o].val = val;        node[o].cover = true;        node[o].a1 = node[o].d = 0;        return ;    }    pushDown(o);    int M = (L + R)/2;    if(ql <= M) setValue(lson, ql, qr, val);    if(qr > M) setValue(rson, ql, qr, val);    pushUp(o);}ll query(int o, int L, int R, int ql, int qr) {    if(ql <= L && R <= qr)        return node[o].sum;    pushDown(o);    int M = (L + R)/2;    ll ret = 0;    if(ql <= M) ret += query(lson, ql, qr);    if(qr > M) ret += query(rson, ql, qr);    return ret;}int main() {    build(1, 1, N);    int T;    scanf("%d", &T);    char oper[5];    int ql, qr, val;    while(T--) {        scanf("%s%d%d", oper, &ql, &qr);        if(oper[0] == 'A') {            modify(1, 1, N, ql, qr, 1);        }else if(oper[0] == 'B') {            modify(1, 1, N, ql, qr, -1);        }else if(oper[0] == 'C') {            scanf("%d", &val);            setValue(1, 1, N, ql, qr, val);        }else if(oper[0] == 'S') {            printf("%lld\n", query(1, 1, N, ql, qr));        }    }    return 0;}
0 0
原创粉丝点击