现在的位置: 首页 > 综合 > 正文

UESTC 1425 Another LCIS

2019年04月07日 ⁄ 综合 ⁄ 共 1856字 ⁄ 字号 评论关闭

大意:求区间最长连续上升序列。

思路:维护三个值。

1、左、右子树最长连续上升序列的最大值。

2、区间边界值,方便判断是否可以合并。

3、如果可以合并,有vr[lc] < vl[rc],则需记录左子树右边界可以到达的最左端,右子树左边界可以到达的最右端,求区间长度即可。

4、注意细节以及维护的值的更新条件。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

const int maxn = 100010;

#define lc o*2
#define rc o*2+1

int n, m;

/*分别是左、右区间最值,
以及右边界能够到达的最左端,
左边界能够到达的最右端*/
int vl[maxn<<2], vr[maxn<<2], lmost[maxn<<2], rmost[maxn<<2];
int maxv[maxn<<2];

int addv[maxn<<2];

void pushdown(int o)
{
	if(addv[o])
	{
		addv[lc] += addv[o];
		addv[rc] += addv[o];
		vl[lc] += addv[o], vr[lc] += addv[o];
		vl[rc] += addv[o], vr[rc] += addv[o];
		addv[o] = 0;	
	}
}

void pushup(int o, int M)
{
	maxv[o] = max(maxv[lc], maxv[rc]);
	vl[o] = vl[lc], vr[o] = vr[rc];
	lmost[o] = lmost[rc], rmost[o] = rmost[lc];
	if(vr[lc] < vl[rc])
	{
		maxv[o] = max(maxv[o], rmost[rc]-lmost[lc]+1);
		if(rmost[o] >= M) rmost[o] = rmost[rc];
		if(lmost[o] <= M+1) lmost[o] = lmost[lc];
	}
}

void build(int o, int L, int R)
{
	addv[o] = 0;
	if(L == R)
	{
		scanf("%d", &vl[o]);
		vr[o] = vl[o];
		lmost[o] = rmost[o] = L;
		maxv[o] = 1;
		return ;
	}
	int M = L + (R-L)/2;
	build(lc, L, M);
	build(rc, M+1, R);
	pushup(o, M);
}

void update(int o, int y1, int y2, int L, int R, int v)
{
	if(y1 <= L && y2 >= R)
	{
		addv[o] += v;
		vl[o] += v, vr[o] += v;
		return ;
	}
	int M = L + (R-L)/2;
	pushdown(o);
	if(y1 <= M) update(lc, y1, y2, L, M, v);
	if(y2 > M) update(rc, y1, y2, M+1, R, v);
	pushup(o, M);
}

int query(int o, int y1, int y2, int L, int R)
{
	if(y1 <= L && y2 >= R) return maxv[o];
	int M = L + (R-L)/2, ans = 0;
	if(y2 <= M) return query(lc, y1, y2, L, M);
	if(y1 > M) return query(rc, y1, y2, M+1, R);
	ans = max(query(lc, y1, y2, L, M), query(rc, y1, y2, M+1, R));
	if(vr[lc] < vl[rc]) ans = max(ans, min(y2, rmost[rc]) - max(y1, lmost[lc])+1);
	return ans;
}

void read_case()
{
	scanf("%d%d", &n, &m);
	build(1, 1, n);
}

void solve()
{
	read_case();
	char op[5];
	int y1, y2, v;
	while(m--)
	{
		scanf("%s%d%d", op, &y1, &y2);
		if(op[0] == 'q')
		{
			int ans = query(1, y1, y2, 1, n);
			printf("%d\n", ans);
		}
		else
		{
			scanf("%d", &v);
			update(1, y1, y2, 1, n, v);
		}
	}
}

int main()
{
	int T, times = 0;
	scanf("%d", &T);
	while(T--)
	{
		printf("Case #%d:\n", ++times);
		solve();
	}
	return 0;
}

抱歉!评论已关闭.