【线段树】【数据结构】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;}
- 【线段树】【数据结构】Data Structure Special Training 2 T1 setmod 题解
- 【逆序对】【线段树】【树状数组】Data Structure Special Training 1 T1 rotinv 题解
- 【线段树】Data Structure Special Training 1 T2 Rise 题解
- 【主席树】【线段树】Data Structure Special Training 2 T3 intkth 题解
- 【扫描线】【线段树】Data Structure Special Training 2 T2 area 题解
- 【有序链剖】Data Structure Special Training 1 T3 seqmod 题解
- 【CRT】【组合数】Number Theory Special Training T1 eqution 题解
- hdu4217 Data Structure? 线段树
- hdu Data Structure? 线段树
- hdu4217 Data Structure?(线段树)
- HDU 4217 Data Structure?(线段树)
- HDU4217-Data Structure?(线段树)
- hdu 2817 Data Structure? (线段树)
- HDU--4217 -- Data Structure? [线段树]
- hdu-4217-Data Structure? 线段树
- HDU4217 Data Structure(线段树)
- Data Structure: Segment Tree 线段树
- C#数据结构-树 data Structure Tree
- TensorFlow:NameError: name ‘input_data’ is not defined
- stanford-segmenter的使用
- 1099-括号配对问题
- HDU 4726 Kia's Calculation
- 八皇后
- 【线段树】【数据结构】Data Structure Special Training 2 T1 setmod 题解
- [DP]从01背包开始
- 001自动刷新页面
- 感想3
- Javascript中函数、构造函数以及原型的用法区别
- 排序——选择排序之直接选择排序
- 搬瓦工shadowsocks服务器端(Centos)和客户端(Ubuntu)的配置
- 【C++】多个类的DLL封装及调用
- System.getProperty("ENM_HOME")中的值是从哪里获取的