您的位置:首页 > 产品设计 > UI/UE

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

/*
* 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息