[线段树] HDU 3306
来源:互联网 发布:wow数据库 编辑:程序博客网 时间:2024/06/10 00:39
感觉线段树的递归还好hhh
但被这个连续递增子序列折腾的够呛hhh
每个节点不仅仅要保存当前最长序列的大小,还要保存前缀和后缀最长序列的大小,以达到正确合并
(自己完全想不出来hhhh)
开始看了代码也是一阵懵逼,把树画出来之后好看很多
#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#define lson rt << 1#define rson rt << 1 | 1using namespace std;const int e = 1000000;int num[ e ];int pre[ e << 2 ]; //保存当前区间从最左开始,连续增长序列的大小(前缀)int suf[ e << 2 ]; //保存当前区间从最右开始,连续增长序列的大小(后缀)int mid[ e << 2 ]; //保存当前区间整个,连续增长序列的大小 // 修改pre,mid,suf保证区间内的序列长度void pushup ( int rt, int l, int r ) { mid[ rt ] = max ( mid[ lson ], mid[ rson ] ); //默认的序列大小为左右两个孩子的序列大小中较大的数 pre[ rt ] = pre[ lson ]; //根的前缀由左孩子的前缀决定 suf[ rt ] = suf[ rson ]; //根的后缀由右孩子的后缀决定 int m = ( l + r ) >> 1; int len = r - l + 1; if ( num[ m ] < num[ m + 1 ] ) { //当前根的左右孩子可以连成一条新的连续序列 mid[ rt ] = max ( mid[ rt ], suf[ lson ] + pre[ rson ] ); //左孩子后缀 + 右孩子前缀 if ( pre[ lson ] == len - len / 2 ) //如果左孩子前缀的大小等于左孩子这段区间的大小 pre[ rt ] += pre[ rson ]; //则根节点的前缀就可以再连上右孩子的前缀 if ( suf[ rson ] == len / 2 ) //右孩子同理 suf[ rt ] += suf[ lson ]; }}void build ( int rt, int l, int r ) { if ( l == r ) { mid[ rt ] = pre[ rt ] = suf[ rt ] = 1; return; } int m = ( l + r ) >> 1; build ( lson, l, m ); build ( rson, m + 1, r ); pushup ( rt, l, r );}//单节点更新void update ( int rt, int l, int r, int idx, int val ) { if ( l == r ) if ( l == idx ) { num[ idx ] = val; pre[ rt ] = mid[ rt ] = suf[ rt ] = 1; return; } int m = ( l + r ) >> 1; if ( idx <= m ) update ( lson, l, m, idx, val ); if ( idx > m ) update ( rson, m + 1, r, idx, val ); pushup ( rt, l, r );}// l,r-->now// L,R-->requiredint query ( int rt, int l, int r, int L, int R ) { //完全在区间里 if ( l >= L && r <= R ) return mid[ rt ]; int m = ( l + r ) >> 1; //完全在左孩子的区间里 if ( R <= m ) return query ( lson, l, m, L, R ); //完全在右孩子的区间里 if ( L > m ) return query ( rson, m + 1, r, L, R ); //部分在左区间部分在右区间 int res = max ( query ( lson, l, m, L, R ), query ( rson, m + 1, r, L, R ) ); if ( num[ m ] < num[ m + 1 ] ) { int prex = min ( suf[ lson ], m - L + 1 ); //取左孩子后缀 和 所求区间在左孩子区间里的大小 的 较小值 int suf = min ( pre[ rson ], R - m ); res = max ( res, prex + suf ); } return res;}int main () { int T; scanf ( "%d", &T ); while ( T-- ) { int n, m; scanf ( "%d%d", &n, &m ); for ( int i = 1; i <= n; ++i ) scanf ( "%d", &num[ i ] ); build ( 1, 1, n ); while ( m-- ) { char ins[ 5 ]; int a, b; scanf ( "%s%d%d", ins, &a, &b ); if ( ins[ 0 ] == 'U' ) update ( 1, 1, n, ++a, b ); else if ( ins[ 0 ] == 'Q' ) { int c = query ( 1, 1, n, ++a, ++b ); printf ( "%d\n", c ); } } } return 0;}
阅读全文
0 0
- [线段树] HDU 3306
- hdu 1754 线段树
- hdu 1754 线段树
- HDU 1698 线段树
- hdu 1754 线段树
- 【线段树】hdu 1754
- hdu-1166 线段树
- HDU-2688 线段树
- HDU 4027 线段树
- HDU-1166 线段树
- hdu 1166 线段树
- hdu 1754 线段树
- hdu 1754 线段树
- hdu 4027#线段树
- hdu 1754 线段树
- HDU-4351-线段树
- hdu 2795 线段树
- hdu 1540 线段树
- 反射
- 互联网协议入门(一)
- 数字图像处理(第三版)—bmp图像的格式
- 大概整理下升级到Android Studio3.0遇到的问题
- linux centos7下QT5添加log4cplus库开发
- [线段树] HDU 3306
- 醒题
- URI与URL、URN笔记
- Java:String、StringBuffer、StringBuilder之间的区别
- 关于python文件操作
- 登陆成功5s后倒计时跳转(http响应头refresh,location)
- Redis之与redis关联使用的脚本lua的基本语法
- Eventbus3.0入(踩)门(坑)之旅
- 猜数字小game