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

ACDream 1101 瑶瑶想要玩滑梯 线段树

2017年10月15日 ⁄ 综合 ⁄ 共 2590字 ⁄ 字号 评论关闭

瑶瑶想要玩滑梯

Time Limit:10000/5000 MS (Java/Others)

 Memory Limit:512000/256000 KB (Java/Others)

Problem Description

众所周知,瑶瑶(tsyao)是个贪玩的萌妹子,特别喜欢闹腾,恰好今天是一个风和日丽的日子,瑶瑶嚷着让姐姐带她去去公园玩滑梯,可是公园的滑梯比较独特,由单位积木搭成,积木是排成一排搭好,每列有xi个积木,共n列。小明能够对积木进行m次操作:

1.U L R yi         : 将[L,R]列的积木高度全都改为yi

2.Q L R           : 查询[L,R]列最长连续上升的列长度(LCIS)

知道[L,R]列最长连续上升的列长度过后,瑶瑶就可以开开心心地玩滑梯啦!

Ps:连续上升的列长度指对于一段合法区间,都有

       话说积木是平的,瑶瑶是怎么从高处滑到低处的呢??作为姐姐也不知道,很想知道吧?你去问她吧。。

Input

第一行 两个整数n,m;

第二行 n个整数,分别为[1,n]区间每列积木个数;

接下来m行为m个操作

Output

输出x行,每行为每次操作2的查询结果。

Sample Input

5 4
2 1 2 3 1
Q 1 4
Q 2 5
U 2 4 3
Q 1 5

Sample Output

3
3
2

Hint

对于 100%的数据,有1 ≤ n ≤ 10^5 , 1 ≤ m ≤ 10^5 , 1 ≤ xi ≤ 10^8。

单组输入,共10组数据。

Source

tsyao

Manager

tsyao
传送门:ACDream 1101 瑶瑶想要玩滑梯
题目大意:给你一个区间,每次修改可以修改一段区间的值,每次查询一个区间问这个区间上的最长连续上升的列长度(LCIS)是多长(严格上升)。
题目分析:这题可以用线段树求解,模型是区间替换和区间合并,只要维护每个区间的左右端点即可。

代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std ;

#define lson l , m , o << 1
#define rson m + 1 , r , o << 1 | 1

const int maxT = 1000000;
const int maxN = 100005;
int a[ maxN ] ;
int maxo[ maxT ] , maxl[ maxT ] , maxr[ maxT ] ;
int numl[ maxT ] , numr[ maxT ] , mark[ maxT ] ;

int max ( const int X , const int Y ) {
	return X > Y ? X : Y ;
}

int min ( const int X , const int Y ) {
	return X < Y ? X : Y ;
}

void PushUp ( int l , int r , int o ) {
	int m = ( l + r ) >> 1 ;
	maxo[ o ] = max ( maxo[ o << 1 ] , maxo[ o << 1 | 1 ] ) ;
	maxl[ o ] = maxl[ o << 1 ] ;
	maxr[ o ] = maxr[ o << 1 | 1 ] ;
	numl[ o ] = numl[ o << 1 ] ;
	numr[ o ] = numr[ o << 1 | 1 ] ;
	if ( numr[ o << 1 ] < numl[ o << 1 | 1 ] ) {
		maxo[ o ] = max ( maxo[ o ] , maxr[ o << 1 ] + maxl[ o << 1 | 1 ] ) ;
		if ( maxl[ o ] == m - l + 1 ) {
			maxl[ o ] += maxl[ o << 1 | 1 ] ;
		}
		if ( maxr[ o ] == r - m ) {
			maxr[ o ] += maxr[ o << 1 ] ;
		}
	}
}

void PushDown ( int o ) {
	if ( mark[ o ] ) {
		mark[ o << 1 ] = mark[ o << 1 | 1 ] = mark[ o ] ;
		numl[ o << 1 ] = numr[ o << 1 ] = mark[ o << 1 ] ;
		maxl[ o << 1 ] = maxr[ o << 1 ] = maxo[ o << 1 ] = 1 ;
		numl[ o << 1 | 1 ] = numr[ o << 1 | 1 ] = mark[ o << 1 | 1 ] ;
		maxl[ o << 1 | 1 ] = maxr[ o << 1 | 1 ] = maxo[ o << 1 | 1 ] = 1 ;
		mark[ o ] = 0 ;
	}
}

void Build ( int l , int r , int o ) {
	mark[ o ] = 0 ;
	if ( l == r ) {
		maxo[ o ] = maxl[ o ] = maxr[ o ] = 1 ;
		numl[ o ] = numr[ o ] = a[ l ] ;
	}
	else {
		int m = ( l + r ) >> 1 ;
		Build ( lson ) ;
		Build ( rson ) ;
		PushUp ( l , r , o ) ;
	}
}

void Update ( int L , int R , int c , int l , int r , int o ) {
	if ( L <= l && r <= R ) {
		maxo[ o ] = maxl[ o ] = maxr[ o ] = 1 ;
		numl[ o ] = numr[ o ] = mark[ o ] = c ;
		return ;
	}
	PushDown ( o ) ;
	int m = ( l + r ) >> 1 ;
	if ( L <= m ) Update ( L , R , c , lson ) ;
	if ( m <  R ) Update ( L , R , c , rson ) ;
	PushUp ( l , r , o ) ;
}

int Query ( int L , int R , int l , int r , int o ) {
	if ( L <= l && r <= R ) return maxo[ o ] ;
	PushDown ( o ) ;
	int tmp1 = 0 , tmp2 = 0 , tmp3 = 0 , m = ( l + r ) >> 1 ;
	if ( L <= m ) tmp1 = Query ( L , R , lson ) ;
	if ( m <  R ) tmp2 = Query ( L , R , rson ) ;
	if ( L <= m && m < R ) {
		if ( numr[ o << 1 ] < numl[ o << 1 | 1 ] ) {
			tmp3 = min ( maxr[ o << 1 ] , m - L + 1 ) + min ( maxl[ o << 1 | 1 ] , R - m ) ;
		}
	}
	return max ( tmp1 , max ( tmp2 , tmp3 ) ) ;
}

void work () {
	int n , m , L , R , C;
	char ch[ 5 ] ;
	scanf ( "%d%d" , &n , &m ) ;
	for ( int i = 1 ; i <= n ; ++ i ) {
		scanf ( "%d", &a[i] ) ;
	}
	Build ( 1 , n , 1 ) ;
	for ( int i = 0 ; i < m ; ++ i ) {
		scanf ( "%s" , ch ) ;
		if ( ch[ 0 ] == 'U' ) {
			scanf ( "%d%d%d" , &L , &R , &C ) ;
			Update ( L , R , C , 1 , n , 1 ) ;
		}
		else {
			scanf ( "%d%d" , &L , &R ) ;
			int ans = Query ( L , R , 1 , n , 1 ) ;
			printf ( "%d\n" , ans ) ;
		}
	}
}
		

int main () {
	work () ;
	return 0 ;
}

抱歉!评论已关闭.