HDU 3308 LCIS(线段树)

Problem Description

Given n integers.
You have two operations:
U A
B: replace the Ath number by B. (index counting from 0)
Q A B: output the
length of the longest consecutive increasing subsequence (LCIS) in [a, b].

Input

T in the first line, indicating the case
number.
Each case starts with two integers n ,
m(0<n,m<=105).
The next line has n
integers(0<=val<=105).
The next m lines each has an
operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A
B(0<=A<=B< n).

Output

For each Q, output the answer.

题目大意:给n个数,动态地修改某个数的值,或者查询一段区间的LCIS(最长连续上升子序列,坑爹的标题……)。

思路:线段树,每个点维护一个区间的从左边开始的最长的LCIS,从右边开始的最长的LCIS,这个区间最大的LCIS。然后随便搞搞就能过了……

代码(593MS):

 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6
7 const int MAXN = 100010 << 2;
8
9 int lmax[MAXN], rmax[MAXN], mmax[MAXN];
10 int a[MAXN], n, m, T;
11
12 void update(int x, int l, int r, int pos, int val) {
13 if(pos <= l && r <= pos) {
14 a[pos] = val;
15 } else {
16 int ll = x << 1, rr = ll | 1, mid = (l + r) >> 1;
17 if(pos <= mid) update(ll, l, mid, pos, val);
18 if(mid < pos) update(rr, mid + 1, r, pos, val);
19 if(a[mid] < a[mid + 1]) {
20 lmax[x] = lmax[ll] + (lmax[ll] == mid - l + 1) * lmax[rr];
21 rmax[x] = rmax[rr] + (rmax[rr] == r - mid) * rmax[ll];
22 mmax[x] = max(rmax[ll] + lmax[rr], max(mmax[ll], mmax[rr]));
23 } else {
24 lmax[x] = lmax[ll];
25 rmax[x] = rmax[rr];
26 mmax[x] = max(mmax[ll], mmax[rr]);
27 }
28 }
29 }
30
31 int query(int x, int l, int r, int aa, int bb) {
32 if(aa <= l && r <= bb) {
33 return mmax[x];
34 } else {
35 int ll = x << 1, rr = ll | 1, mid = (l + r) >> 1;
36 int ans = 0;
37 if(aa <= mid) ans = max(ans, query(ll, l, mid, aa, bb));
38 if(mid < bb) ans = max(ans, query(rr, mid + 1, r, aa, bb));
39 if(a[mid] < a[mid + 1]) ans = max(ans, min(rmax[ll], mid - aa + 1) + min(lmax[rr], bb - mid));
40 return ans;
41 }
42 }
43
44 void build(int x, int l, int r) {
45 if(l == r) {
46 lmax[x] = rmax[x] = mmax[x] = 1;
47 } else {
48 int ll = x << 1, rr = ll | 1, mid = (l + r) >> 1;
49 build(ll, l, mid);
50 build(rr, mid + 1, r);
51 if(a[mid] < a[mid + 1]) {
52 lmax[x] = lmax[ll] + (lmax[ll] == mid - l + 1) * lmax[rr];
53 rmax[x] = rmax[rr] + (rmax[rr] == r - mid) * rmax[ll];
54 mmax[x] = max(rmax[ll] + lmax[rr], max(mmax[ll], mmax[rr]));
55 } else {
56 lmax[x] = lmax[ll];
57 rmax[x] = rmax[rr];
58 mmax[x] = max(mmax[ll], mmax[rr]);
59 }
60 }
61 }
62
63 int main() {
64 scanf("%d", &T);
65 while(T--) {
66 scanf("%d%d", &n, &m);
67 for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
68 build(1, 0, n - 1);
69 while(m--) {
70 char c;
71 int a, b;
72 scanf(" %c%d%d", &c, &a, &b);
73 if(c == ‘Q‘) printf("%d\n", query(1, 0, n - 1, a, b));
74 else update(1, 0, n - 1, a, b);
75 }
76 }
77 }

HDU 3308 LCIS(线段树),布布扣,bubuko.com

时间: 2024-10-27 11:55:01

HDU 3308 LCIS(线段树)的相关文章

hdu 3308 LCIS(线段树)

pid=3308" target="_blank" style="">题目链接:hdu 3308 LCIS 题目大意:给定一个序列,两种操作: Q l r:查询区间l,r中的最长连续递增序列长度 U p x:将位置p上的数改成x 解题思路:线段树上的区间合并,这是在左右子树合并的时候要推断一下是否满足递增就可以. #include <cstdio> #include <cstring> #include <algorit

HDU 3308 LCIS 线段树 区间更新

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目描述: 有两种操作, U x y  , 第xth赋值为y .Q x y , 查询区间x-y的最长连续上升子序列的长度L 解题思路: 对于线段树不好的我依然好难.....有太多细节需要注意了....但是这是一道很好的题, 一段区间的L可能从三个地方来, 一种是中间, 一种是以左起点为开头的, 一种是以右起点结尾的, 这样查询的时候就要注意了: 如果两段的中间值是a[m] < a[m+1]

HDU 3308 LCIS (线段树区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1

HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出对应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  对应区间的LCIS长度(lcis)  对应区间以左端点为起点的LCIS长度(lle)  对应区间以右端点为终点的LCIS长度(lri)  然后用val存储数组对应位置的值  当val[mid + 1] > val[mid] 的时候就要进行区间合并操作了 #include <cstdio> #include <algorithm>

HDU 3308 LCIS(线段树区间合并)

Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting from 0) Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. Input T in the first line, indicat

hdu 3308(线段树)

线段树求区间最长连续上升 #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn=1e5+100; int ll[maxn<<2],rr[maxn<<2];//左边的连续上升子序列长度和右边的连续上升子序列长度 int a[maxn]; int mx[maxn<

HDU - 3308 - LCIS (线段树 - 区间合并)

题目传送:LCIS 线段树,区间合并,一次过啦,没有纠结,这几天过的最愉快的一个题 思路:求最长连续上升子序列,外带单点更新,经典的线段树题目.具体看代码注释 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack>

HDU 3308 LCIS (端点更新+区间合并)

刚刚做了两道LCIS,碰到这道线段树,脑抽了似的写 线段树+dp(LCIS),贡献一发TLE. 才想到要区间合并,query函数写了好久.下面有详细注释,参见代码吧~~欢迎点赞,欢迎卖萌~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 #include<cstdio> #inc

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid