【线段树】【数据结构】Data Structure Special Training 2 T1 setmod 题解

来源:互联网 发布:淘宝手机充值怎么退款 编辑:程序博客网 时间:2024/06/17 23:57

Problem 1. setmod
Input file: setmod.in
Output file: setmod.out
Time limit: 2 seconds
Memory limit: 256 MB
给你一个序列:a1 a2 a3 : : : an,有m 个操作,操作如下:
• modify l r x  将区间[l; r] 中的每个数修改为x
• change l r x 将区间[l; r] 中的每个数加上x
• query l r 询问区间[l; r] 中的和
Input
第1 行2 个整数:n m,表示序列长的和操作数.
第2 行n 个整数:a1 a2 a3 : : : an,表示初始序列.
接下来m 行,每行是上面三种操作中的一种.
Output
对于每个询问操作,输出其结果.
Sample
setmod.in setmod.out
3 3
1 2 3
change 1 3 2
modify 3 3 3
query 1 3
10
Note
• 对于30% 的数据,1  n;m  103
• 对于100% 的数据,1  n;m  105,1  ai; x  n,1  l  r  n
Page 1

PS
神奇的数据有 r > l 的数据,当 r > l 时不处理,询问输出0

Hint
普通线段树,打俩lazy标记,modify可以覆盖change

题解
1.1 30%
O(nm) 暴力。
1.2 100%
要维护几个东西:
• sum 表示区间的和
• type 表示现在的标记类型(可以是没有标记,可以是增量标记,可以是
赋值标记)
• delta 如果是增量标记,那么这个里面存的增量
• value 如果是赋值标记,那么这里面就存的是那个值
然后就秩序要讨论一下发现:
• 空标记+ 赋值操作= 赋值标记
• 空标记+ 增量操作= 增量标记
• 增量标记+ 赋值操作= 赋值标记
• 增量标记+ 增量操作= 增量标记
• 赋值标记+ 增量操作= 赋值标记
• 赋值标记+ 赋值操作= 赋值标记
因为它们之间能和谐共处(如果A 标记遇见B 操作无法转化为一种现有的标
记,那么他们就不能同时用线段树实现),所以就能完成两种操作同时进行。具
体看代码是怎样合并的。

#include<iostream>#include<cstdio>#include<ctime>#include<cctype>#include<cstring>#include<cstdlib>#include<fstream>#include<sstream>#include<algorithm>#include<map>#include<set>#include<stack>#include<queue>#include<vector>#define llf (1LL << 60)using namespace std;template <class T> inline void read(T &x) {    int flag = 1; x = 0;    char ch = getchar();    while(ch <  '0' || ch >  '9') { if(ch == '-')  flag = -1; ch = getchar(); }    while(ch >= '0' && ch <= '9') { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); }    x *= flag;}inline char Read() {    char ch = getchar();    while(ch == ' ' || ch == '\n') ch = getchar();    return ch;}typedef struct SegTreeNode {    public:        long long val;        SegTreeNode *l, *r;        long long clazy;        long long mlazy;        SegTreeNode(int val = 0, SegTreeNode* l = NULL, SegTreeNode* r = NULL, long long mlazy = llf, long long clazy = 0):val(val), l(l), r(r), mlazy(mlazy), clazy(clazy) {       }        inline void pushUp() {            this->val = l->val + r->val;        }        inline void pushmDown(int le, int ri, int mid) {            l->val = (mid - le + 1) * mlazy;            r->val = (ri - mid) * mlazy;            l->mlazy = r->mlazy = mlazy;            l->clazy = r->clazy = 0;            mlazy = llf;        }        inline void pushcDown(int le, int ri, int mid) {            l->val += (mid - le + 1) * clazy;            r->val += (ri - mid) * clazy;            l->clazy += clazy, r->clazy += clazy;            clazy = 0;        }}SegTreeNode;typedef struct SegTree {    public:        SegTreeNode* root;        SegTree():root(NULL) {      }        SegTree(int s, int* lis) {            build(root, 1, s, lis);        }        void build(SegTreeNode*& node, int l, int r, int* lis) {            node = new SegTreeNode();            if(l == r) {                node->val = lis[l];                return;            }            int mid = (l + r) >> 1;            build(node->l, l, mid, lis);            build(node->r, mid + 1, r, lis);            node->pushUp();        }        void modify(SegTreeNode*& node, int l, int r, int ml, int mr, int x) {            if(l == ml && r == mr) {                node->val = (r - l + 1) * 1LL * x;                node->mlazy = x, node->clazy = 0;                return;            }            int mid = (l + r) >> 1;            if(node->mlazy != llf) node->pushmDown(l, r, mid);            if(node->clazy) node->pushcDown(l, r, mid);            if(mr <= mid) modify(node->l, l, mid, ml, mr, x);            else if(ml > mid) modify(node->r, mid + 1, r, ml, mr, x);            else {                modify(node->l, l, mid, ml, mid, x);                modify(node->r, mid + 1, r, mid + 1, mr, x);            }            node->pushUp();        }        void update(SegTreeNode*& node, int l, int r, int ml, int mr, int x) {            if(l == ml && r == mr) {                node->val += (r - l + 1) * 1LL * x;                node->clazy += x;                return;            }            int mid = (l + r) >> 1;            if(node->mlazy != llf) node->pushmDown(l, r, mid);            if(node->clazy) node->pushcDown(l, r, mid);            if(mr <= mid)   update(node->l, l, mid, ml, mr, x);            else if(ml > mid)   update(node->r, mid + 1, r, ml, mr, x);            else {                update(node->l, l, mid, ml, mid, x);                update(node->r, mid + 1, r, mid + 1, mr, x);            }            node->pushUp();        }        long long query(SegTreeNode*& node, int l, int r, int ql, int qr) {            if(l == ql && r == qr) {                return node->val;            }            int mid = (l + r) >> 1;            if(node->mlazy != llf) node->pushmDown(l, r, mid);            if(node->clazy) node->pushcDown(l, r, mid);            if(qr <= mid)   return query(node->l, l, mid, ql, qr);            if(ql > mid)    return query(node->r, mid + 1, r, ql, qr);            return query(node->l, l, mid, ql, mid) + query(node->r, mid + 1, r, mid + 1, qr);        }}SegTree;int n, m;int* lis;SegTree st;inline void init() {    read(n);    read(m);    lis = new int[(const int)(n + 1)];    for(int i = 1; i <= n; i++) read(lis[i]);    st = SegTree(n, lis);}char s[11];inline void solve() {    int a, b, x;    while(m--) {        scanf("%s", s);        read(a);        read(b);        if(s[0] == 'm') {            read(x);            if(b > a) continue;            st.modify(st.root, 1, n, a, b, x);        } else if(s[0] == 'c') {            read(x);            if(b > a) continue;            st.update(st.root, 1, n, a, b, x);        } else {            if(b > a) {                printf("0\n");                continue;            }            long long res = st.query(st.root, 1, n, a, b);            cout << res << endl;        }    }}int main() {    freopen("setmod.in", "r", stdin);    freopen("setmod.out", "w", stdout);    init();    solve();    return 0;}
0 0