[HDOJ3308]LCIS(线段树,区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308
题意:给定n个数,两个操作:
U A B:将位置A的数值改成B
Q A B:查询[A,B]内最长连续上升子序列的长度。
注意到‘连续’一词,可以用线段树维护[L,R]区间内的LICS。
定义结构Node,内部l,r为左右儿子的下标。ls,rs记录当前区间分别从左起和右起的LICS长度,s记录整个区间内的LICS长度。
pushup:和一般的区间合并操作一样,但是要注意假如合并的左右子树中间有可能成为LICS的时候,要判断是否符合条件,即左起右边界和右起左边界是否满足严格的关系。
update:更新节点的时候直接赋值,再更新到线段树上的操作也是很常规的。
query:比较奇特,因为有左起右边界和右起左边界连接起来的情况,所以查询的时候不是缩小线段树规模,而是缩小查询规模来获得解。而且要注意[L,R]的边界问题。子树的范围未必恰好满足,可能会更长。
#include <bits/stdc++.h>
using namespace std; #define lrt rt << 1
#define rrt rt << 1 | 1
typedef struct Node {
int l, r;
int ls, s, rs;
}Node;
const int maxn = ;
char cmd[];
int n, q;
int x[maxn];
Node seg[maxn<<]; void pushUP(int rt, int len) {
seg[rt].ls = seg[lrt].ls; seg[rt].rs = seg[rrt].rs;
if(seg[rt].ls == len-len/) {
if(x[seg[lrt].r] < x[seg[rrt].l]) {
seg[rt].ls += seg[rrt].ls;
}
}
if(seg[rt].rs == len/) {
if(x[seg[lrt].r] < x[seg[rrt].l]) {
seg[rt].rs += seg[lrt].rs;
}
}
seg[rt].s = max(seg[lrt].s, seg[rrt].s);
if(x[seg[lrt].r] < x[seg[rrt].l]) {
seg[rt].s = max(seg[rt].s, seg[lrt].rs+seg[rrt].ls);
}
} void build(int l, int r, int rt) {
seg[rt].l = l; seg[rt].r = r;
if(l == r) {
seg[rt].ls = seg[rt].rs = seg[rt].s = ;
return;
}
int mid = (l + r) >> ;
build(l, mid, lrt);
build(mid+, r, rrt);
pushUP(rt, r-l+);
} void update(int L, int R, int rt) {
if(L <= seg[rt].l && seg[rt].r <= R) {
seg[rt].ls = seg[rt].rs = seg[rt].s = ;
return;
}
int mid = (seg[rt].l + seg[rt].r) >> ;
if(L <= mid) update(L, R, lrt);
if(mid < R) update(L, R, rrt);
pushUP(rt, seg[rt].r-seg[rt].l+);
} int query(int L, int R, int rt) {
if(L == seg[rt].l && R == seg[rt].r) return seg[rt].s;
int mid = (seg[rt].l + seg[rt].r) >> ;
if(mid >= R) return query(L, R, lrt);
else if(mid + <= L) return query(L, R, rrt);
else {
int tmp = max(query(L, mid, lrt), query(mid+, R, rrt));
if(x[seg[lrt].r] < x[seg[rrt].l]) {
tmp = max(tmp, min(seg[lrt].rs, mid-L+)+min(seg[rrt].ls, R-mid));
}
return tmp;
}
} int main() {
// freopen("in", "r", stdin);
int T, a, b;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &q);
for(int i = ; i <= n; i++) {
scanf("%d", &x[i]);
}
build(, n, );
while(q--) {
scanf("%s %d %d", cmd, &a, &b);
a++;
if(cmd[] == 'U') {
x[a] = b;
update(a, a, );
}
else {
b++;
printf("%d\n", query(a, b, ));
}
}
}
return ;
}
[HDOJ3308]LCIS(线段树,区间合并)的更多相关文章
- hdu-3308 LCIS (线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
- hud 3308 LCIS 线段树 区间合并
题意: Q a b 查询[a, b]区间的最长连续递增子序列的长度 U a b 将下表为a的元素更新为b 区间合并一般都有3个数组:区间最值,左区间最值和右区间最值 具体详见代码 #include & ...
- LCIS HDU - 3308 (线段树区间合并)
LCIS HDU - 3308 Given n integers. You have two operations: U A B: replace the Ath number by B. (inde ...
- hdu 3308(线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
随机推荐
- yii2 render和renderPartial区别
1.render()方法使用到项目中的布局layout,renderPartial()不使用布局
- javascript中字符串格式json如何转化成json对象
什么是JSON JSON(JavaScript Object Notation)是一种优美的JavaScript对象创建方法.JSON也是一种轻量级数据交换格式.JSON非常易于人阅读与编写,同时利于 ...
- OpenCV 简介
自版本OpenCV2.2开始,OpenCV库便被划分为多个模块.这些模块编译成库文件后,位于lib文件夹中. opencv_core模块,包含核心功能,尤其是底层数据结构和算法函数. opencv_i ...
- Android多线程通信之Handler
主线程 public class MainActivity extends ActionBarActivity { private Handler handler; // private Thread ...
- React+Node.js+Express+mongoskin+MongoDB
首发:个人博客,更新&纠错&回复 采用React + Node.js + Express + mongoskin + MongoDB技术开发的一个示例,演示地址在这里,项目源码在这里. ...
- android 学习随笔二十四(动画:帧动画)
帧动画,一张张图片不断的切换,形成动画效果 * 在drawable目录下定义xml文件,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长 * FrameAnimatio ...
- android 学习随笔二十三(动画:Fragment )
Fragment * 用途:在一个Activity里切换界面,切换界面时只切换Fragment里面的内容 * 在一个Activity中切换多个界面,每个界面就是一个Fragment* Fragmnen ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- webapi获取请求地址的IP
References required: HttpContextWrapper - System.Web.dll RemoteEndpointMessageProperty - System.Serv ...
- Serialize Documents with the C# Driver
1.介绍 该文档是1.8版本的C#驱动. 本节教程讨论C#类和BSON文档之间的序列化和反序列化.序列化是将对象映射成一个可以存储在MongoDB中的BSON文档的过程,反序列化是从一个BSON文档重 ...