码迷,mamicode.com
首页 > 其他好文 > 详细

LCIS线段树(区间更新)

时间:2016-08-12 13:05:37      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

   首先线段树每一个节点包含:[b,e],lmax,rmax,max;其中lmax表示从左端点开始连续的最长的增序列长度,rmax表示从e端点开始向左连续的最长下降序列长度,max表示当前区间的连续递增的最长序列长度。对单个节点插入时的信息维护如下:

   (1) if 左儿子的右端点的值<右儿子的左端点的值

         lmax=左儿子区间长度==左儿子的lmax?左儿子区间长度+右儿子的lmax:左儿子的lmax.

         rmax=右儿子区间长度==右儿子的rmax?右儿子区间长度+左儿子的rmax:右儿子的rmax.

         max=MAX(lmax,rmax,左儿子的rmax+右儿子的lmax);

  (2)否则

        lmax=左儿子的lmax;

        rmax=右儿子的rmax;

        max=MAX(左儿子的max,右儿子的max);

查寻操作如下:

      if 当前节点区间==查询区间

              返回当前节点的max

      否则

             返回 MAX(左区间,右区间,跨越边界的长度)

//------------------------------------------------------------------
//---线段树区间更新
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1000000;
struct Tnode{
	int b, e;
	int lmax;
	int rmax;
	int max;
	int len(){ return e - b + 1; }
};
Tnode tree[4*MAXN];
int p[MAXN];
int n, m;
int max(int a, int b, int c){
	return max(max(a, b), c);
}
void Build(int v, int l, int r){
	tree[v].b = l, tree[v].e = r;
	tree[v].lmax = tree[v].rmax = tree[v].max = 0;
	if (l < r){
		int mid = (l + r) >> 1;
		Build(2 * v + 1, l, mid);
		Build(2 * v + 2, mid + 1, r);
	}
}
void Insert(int v, int k, int val){
	if (tree[v].b == tree[v].e){
		//找到叶节点插入 
		p[k] = val;
		tree[v].lmax = tree[v].rmax = tree[v].max = 1;
		return;
	}
	int mid = (tree[v].b + tree[v].e) >> 1;
	if (k <= mid)
		Insert(2 * v + 1, k, val);
	else
		Insert(2 * v + 2, k, val);
	//接下来更新
	if (p[mid] < p[mid + 1]){
		if (tree[2 * v + 1].lmax == tree[2 * v + 1].len())
			tree[v].lmax = tree[2 * v + 1].len() + tree[2 * v + 2].lmax;
		else
			tree[v].lmax = tree[2*v+1].lmax;

		if (tree[2 * v + 2].rmax == tree[2 * v + 2].len())
			tree[v].rmax = tree[2 * v + 2].len() + tree[2 * v + 1].rmax;
		else
			tree[v].rmax = tree[2*v+2].rmax;
		tree[v].max = max(tree[2 * v + 1].max, tree[2 * v + 2].max,tree[2 * v + 1].rmax + tree[2 * v + 2].lmax);
	}
	else{
		tree[v].lmax = tree[2*v+1].lmax;
		tree[v].rmax = tree[2 * v + 2].rmax;
		tree[v].max = max(tree[2 * v + 1].max,tree[2 * v + 2].max);
	}
}
int Qurrey(int v,int l, int r){
	if (l == tree[v].b&&r == tree[v].e)
		return tree[v].max;
	int mid = (tree[v].b + tree[v].e) >> 1;
	if (r <= mid)
		return Qurrey(2 * v + 1, l, r);
	else if (l > mid)
		return Qurrey(2 * v + 2, l, r);
	else{
		if (p[mid] < p[mid + 1]){
			int left = max(mid + 1 - tree[2 * v + 1].rmax, l);
			int right = min(r, mid + tree[2 * v + 2].lmax);
			return max(Qurrey(2 * v + 1, l, mid), Qurrey(2 * v + 2, mid + 1, r), right-left+1);
		}
		else
			return  max(Qurrey(2 * v + 1, l, mid), Qurrey(2 * v + 2, mid + 1, r));
	} 
}
int main(){
	int i, T,a,b;
	char s;
	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		memset(p, 0, sizeof(p));
		Build(0, 0, n - 1);
		for (i = 0; i < n; i++){
			scanf("%d", &p[i]);
			Insert(0, i, p[i]);
		}
		while (m--){
			cin >> s;
			scanf("%d%d",&a, &b);
			if (s == ‘U‘)
				Insert(0, a, b);
			else
				printf("%d\n", Qurrey(0, a, b));
		}
	}
	return 0;
}

  

LCIS线段树(区间更新)

标签:

原文地址:http://www.cnblogs.com/td15980891505/p/5764334.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!