UESTC 360 Another LCIS (线段树 维护LCIS)
2015-08-18 19:35
429 查看
题目大意:
就是对于数列S, 长度不超过1e5, 有两种操作, 第一种是将一个区间当中的所有数加上一个值, 你一种是询问一个区间中的LCIS的长度, LCIS指最长连续上升子序列
大致思路:
考虑到线段树维护两个区间的时候满足的是广义的加法, 那么要通过两个区间的LCIS的信息得到合并的区间的LCIS的信息的话, 就需要维护者6个元素:
对于每一个子区间, 维护:
1. 区间左界的值L
2. 区间右界的值R
3. 区间从左界开始能得到的LCIS的长度
4. 区间以右界作为结尾能得到的LCIS的长度
5. 不限制LCIS位置, 能得到的LCIS的长度
6. 区间长度
那么当两个区间合并的时候, 除了继承左区间的L, 左界LCIS长度, 和右区间的R, 右界LCIS长度, 以及两个区间不限制位置的LCIS最大值之外, 当左界开始的LCIS长度能达到左区间长度时, 考虑左区间右界和右区间左界的大小来判断是否能够合并得到更大的LCIS即可, 区间的L, R在区间增减的时候需要用懒惰标记记录
代码如下:
Result : Accepted Memory : 8176 KB Time : 211 ms
就是对于数列S, 长度不超过1e5, 有两种操作, 第一种是将一个区间当中的所有数加上一个值, 你一种是询问一个区间中的LCIS的长度, LCIS指最长连续上升子序列
大致思路:
考虑到线段树维护两个区间的时候满足的是广义的加法, 那么要通过两个区间的LCIS的信息得到合并的区间的LCIS的信息的话, 就需要维护者6个元素:
对于每一个子区间, 维护:
1. 区间左界的值L
2. 区间右界的值R
3. 区间从左界开始能得到的LCIS的长度
4. 区间以右界作为结尾能得到的LCIS的长度
5. 不限制LCIS位置, 能得到的LCIS的长度
6. 区间长度
那么当两个区间合并的时候, 除了继承左区间的L, 左界LCIS长度, 和右区间的R, 右界LCIS长度, 以及两个区间不限制位置的LCIS最大值之外, 当左界开始的LCIS长度能达到左区间长度时, 考虑左区间右界和右区间左界的大小来判断是否能够合并得到更大的LCIS即可, 区间的L, R在区间增减的时候需要用懒惰标记记录
代码如下:
Result : Accepted Memory : 8176 KB Time : 211 ms
/* * Author: Gatevin * Created Time: 2015/8/18 18:40:20 * File Name: Sakura_Chiyo.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; #define maxn 100010 struct Segment_Tree { struct State { int left, mid, right;//左界开始的LCIS长度, 此区间的LCIS长度, 右界结尾的LCIS长度 int L, R;//区间的左右端点的值 int len;//区间长度 State(int _l, int _m, int _r, int _L, int _R, int _len) { left = _l, mid = _m, right = _r, L = _L, R = _R, len = _len; } State(){} }; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 State s[maxn << 2]; int flag[maxn << 2];//懒惰标记记录区间增量 void pushUp(int rt) { s[rt] = State(s[rt << 1].left, max(s[rt << 1].mid, s[rt << 1 | 1].mid), s[rt << 1 | 1].right, s[rt << 1].L, s[rt << 1 | 1].R, s[rt << 1].len + s[rt << 1 | 1].len); if(s[rt << 1].R < s[rt << 1 | 1].L) { if(s[rt << 1].left == s[rt << 1].len) s[rt].left = s[rt << 1].left + s[rt << 1 | 1].left; if(s[rt << 1 | 1].right == s[rt << 1 | 1].len) s[rt].right = s[rt << 1].right + s[rt << 1 | 1].right; s[rt].mid = max(s[rt].mid, s[rt << 1].right + s[rt << 1 | 1].left); } return; } void pushDown(int rt)//向下推动flag懒惰标记 { if(flag[rt]) { flag[rt << 1] += flag[rt]; flag[rt << 1 | 1] += flag[rt]; s[rt << 1].L += flag[rt]; s[rt << 1].R += flag[rt]; s[rt << 1 | 1].L += flag[rt]; s[rt << 1 | 1].R += flag[rt]; flag[rt] = 0; } return; } void build(int l, int r, int rt) { flag[rt] = 0; if(l == r) { int tmp; scanf("%d", &tmp); s[rt] = State(1, 1, 1, tmp, tmp, 1); return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(rt); } void update(int l, int r, int rt, int L, int R, int value)//区间[L, R]增加value { if(l >= L && r <= R) { s[rt].L += value; s[rt].R += value; flag[rt] += value; return; } int mid = (l + r) >> 1; pushDown(rt); if(mid >= L) update(lson, L, R, value); if(mid + 1 <= R) update(rson, L, R, value); pushUp(rt); return; } State query(int l, int r, int rt, int L, int R)//询问区间[L, R]的LCIS长度 { if(l >= L && r <= R) return s[rt]; int mid = (l + r) >> 1; pushDown(rt); State sl, sr; bool fl = 0, fr = 0; if(mid >= L) sl = query(lson, L, R), fl = 1; if(mid + 1 <= R) sr = query(rson, L, R), fr = 1; //pushUp(rt); if(!fl) return sr; if(!fr) return sl; State ret = State(sl.left, max(sl.mid, sr.mid), sr.right, sl.L, sr.R, sl.len + sr.len); if(sl.R < sr.L) { if(sl.left == sl.len) ret.left = sl.left + sr.left; if(sr.right == sr.len) ret.right = sl.right + sr.right; ret.mid = max(ret.mid, sl.right + sr.left); } return ret; } void solve(int cas, int n, int Q) { printf("Case #%d:\n", cas); build(1, n, 1); char op[4]; int l, r, val; while(Q--) { scanf("%s", op); switch(op[0]) { case 'q': scanf("%d %d", &l, &r); printf("%d\n", query(1, n, 1, l, r).mid); break; case 'a': scanf("%d %d %d", &l, &r, &val); update(1, n, 1, l, r, val); break; } } return; } }; Segment_Tree ST; int main() { int T, n, Q; scanf("%d", &T); for(int cas = 1; cas <= T; cas++) { scanf("%d %d", &n, &Q); ST.solve(cas, n, Q); } return 0; }
相关文章推荐
- 线段树题集
- hdu1754
- HDU1394
- 敌兵布阵 (1)
- I Hate It (1)
- LCIS (2)
- A Simple Problem with Integers (2)
- Mayor's posters (3)
- Buy Tickets (3)
- 线段树
- UVA - 12532 Interval Product
- POJ 3264 Balanced Lineup
- hdu 1542 求矩形并的面积
- 关于数据结构之线段树
- poj 3225 关于集合运算
- poj 2352
- hdu1166敌兵布阵(线段树点修改)
- POJ 2352 Stars 线段树 pascal
- hdu 1698 Just A Hook 线段树的一道题
- HDU 1754 I Hate It