任意区间的最长连续递增子序列,最大连续子序列和

hdu3308

给n个数,有m个操作

U a b 表示将第a个数改成b

Q a b 表示询问区间[a,b]的最长连续递增子序列。

区间询问问题且带修改,一般是用线段树来解决

那么要维护

Llen[rt], Lval[rt][2] 表示rt所对应的区间[l,r] 以l开头的最长连续递增子序列的长度, Lval[rt][0]表示子序列的最左边的值,Lval[rt][1]表示子序列最右边的值

Rlen[rt],Rval[rt][2]  表示rt所对应的区间[l,r]以r结尾的最长连续递增子序列的长度, Rval[rt][0] 表示子序列最左边的值,Rval[rt][1]表示子序列最右边的值

Mlen[rt] 表示rt所对应的区间[l,r]最长连续递增子序列的长度

那么Llen[rt] 可能是左区间的Llen[rt<<1]  ,也有可能是跨越左右两个孩子

Rlen[rt] 可能是右区间的Rlen[rt<<1|1],  页有可能是跨越左右两个孩子

Mlen[rt] 可能是左区间的Mlen[rt<<1],或者右区间的Mlen[rt<<1|1], 也有可能跨越左右两个区间

上面的状态转移时,也要注意一下val的改变。

具体的转移见代码

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 using namespace std;
  5
  6 /*
  7
  8
  9 */
 10 const int N = 100000 + 10;
 11 int a[N];
 12 int Llen[N*4],Lval[N*4][2],Rlen[N*4],Rval[N*4][2],Mlen[N*4];
 13
 14 void pushUp(int rt, int l, int r)
 15 {
 16     int mid = (l+r)>>1;
 17     int tmp = 0;
 18     if(Rval[rt<<1][1] < Lval[rt<<1|1][0])
 19         tmp = Rlen[rt<<1] + Llen[rt<<1|1];
 20     Mlen[rt] = max(tmp,max(Mlen[rt<<1],Mlen[rt<<1|1]));
 21     if(Llen[rt<<1]==mid-l+1 &&Lval[rt<<1][1] <Lval[rt<<1|1][0])
 22     {
 23         Llen[rt] = Llen[rt<<1] + Llen[rt<<1|1];
 24         Lval[rt][0] = Lval[rt<<1][0];
 25         Lval[rt][1] = Lval[rt<<1|1][1];
 26     }
 27     else
 28     {
 29         Llen[rt] = Llen[rt<<1];
 30         Lval[rt][0] = Lval[rt<<1][0];
 31         Lval[rt][1] = Lval[rt<<1][1];
 32     }
 33     if(Rlen[rt<<1|1]==r-mid && Rval[rt<<1|1][0]>Rval[rt<<1][1])
 34     {
 35         Rlen[rt] = Rlen[rt<<1] + Rlen[rt<<1|1];
 36         Rval[rt][0] = Rval[rt<<1][0];
 37         Rval[rt][1] = Rval[rt<<1|1][1];
 38     }
 39     else
 40     {
 41         Rlen[rt] = Rlen[rt<<1|1];
 42         Rval[rt][0] = Rval[rt<<1|1][0];
 43         Rval[rt][1] = Rval[rt<<1|1][1];
 44     }
 45
 46 }
 47 void build(int l, int r, int rt)
 48 {
 49     if(l==r)
 50     {
 51         Llen[rt] = Rlen[rt] = Mlen[rt] = 1;
 52         Lval[rt][0] = Lval[rt][1] = Rval[rt][0] = Rval[rt][1] =  a[l];
 53         return ;
 54     }
 55     int mid = (l+r)>>1;
 56     build(l,mid,rt<<1);
 57     build(mid+1,r,rt<<1|1);
 58     pushUp(rt,l,r);
 59 }
 60 void update(int l, int r, int rt, int pos)
 61 {
 62     if(l==r)
 63     {
 64         Lval[rt][0] = Lval[rt][1] = Rval[rt][0] = Rval[rt][1] = a[l];
 65         return;
 66     }
 67     int mid = (l+r)>>1;
 68     if(pos<=mid)
 69         update(l,mid,rt<<1,pos);
 70     else
 71         update(mid+1,r,rt<<1|1,pos);
 72     pushUp(rt,l,r);
 73 }
 74
 75 int llen,rlen,mlen,lval[2],rval[2];
 76 bool f;
 77 void query(int l, int r, int rt, int L, int R)
 78 {
 79     if(L<=l &&R>=r)
 80     {
 81        if(f)
 82        {
 83            f = false;
 84            llen = Llen[rt];
 85            rlen = Rlen[rt];
 86            mlen = Mlen[rt];
 87            lval[0] = Lval[rt][0];
 88            lval[1] = Lval[rt][1];
 89            rval[0] = Rval[rt][0];
 90            rval[1] = Rval[rt][1];
 91        }
 92        else
 93        {
 94             int tmp = 0;
 95             if(rval[1]<Lval[rt][0])
 96                 tmp = rlen + Llen[rt];
 97             mlen = max(max(mlen,Mlen[rt]),tmp);
 98             if(llen==l-L && lval[1] < Lval[rt][0])
 99             {
100                 llen = llen + Llen[rt];
101                 lval[1] = Lval[rt][1];
102             }
103
104             if(Rlen[rt]==r-l+1 && Rval[rt][0]>rval[1])
105             {
106                 rlen = Rlen[rt] + rlen;
107                 rval[1] = Rval[rt][1];
108             }
109             else
110             {
111                 rlen = Rlen[rt];
112                 rval[0] = Rval[rt][0];
113                 rval[1] = Rval[rt][1];
114             }
115
116        }
117         return;
118     }
119     int mid = (l+r)>>1;
120     if(L<=mid)
121         query(l,mid,rt<<1,L,R);
122     if(R>mid)
123         query(mid+1,r,rt<<1|1,L,R);
124 }
125 int main()
126 {
127     int t,n,m;
128     char ch[3];
129     int A,B;
130     scanf("%d",&t);
131     while(t--)
132     {
133         scanf("%d%d",&n,&m);
134         for(int i=1;i<=n;++i)
135             scanf("%d",&a[i]);
136         build(1,n,1);
137         while(m--)
138         {
139             scanf("%s%d%d",ch,&A,&B);
140             if(ch[0]==‘U‘)
141             {
142                 a[A+1] = B;
143                 update(1,n,1,A+1);
144             }
145             else
146             {
147                 f = true;
148                 llen = rlen = mlen = 0;
149                 lval[0] = lval[1] = rval[0] = rval[1] = 0;
150                 query(1,n,1,A+1,B+1);
151                 printf("%d\n",max(max(llen,rlen),mlen));
152             }
153         }
154     }
155     return 0;
156 }

同理,最大连续子序列和,和上面的思路差不多

更难一点的题目就是把上述的两个问题放到树上,  那么就要用到树链剖分。

时间: 2024-11-24 00:07:37

任意区间的最长连续递增子序列,最大连续子序列和的相关文章

最长连续递增子序列(部分有序)

题目:(1,9,2,5,7,3,4,6,8,0,)中最长的递增子序列为(3,4,6,8). 代码: public class 最长递增子序列 { public static void main(String[] args) { int []arr = {1,0,2,5,7,3,4,6,8,9,1,2}; getLargestLen(arr); } private static void getLargestLen(int[] arr) { int begin=0; // 最长递增子序列长度的开始

【算法】——查找:最长连续递增子序列(部分有序)

找出在数组中的最长递增子序列 数组:1,9,2,5,7,3,4,6,8,0 最长递增子序列:3,4,6,8 思路: 遇到大的就移动,如果在某一个位置变小了就计算这一段的长度(双指针)不停更新最大的length一个在前线,一个在后面作为游标,最后结束了看一下战线拉了有多长 public class 最长递增子序列 { public static void main(String[] args) { int []arr = {0,1,0,1,2,3,1,2,0,1,2,3,4,5,1}; getLa

LeetCode 674. 最长连续递增序列(Longest Continuous Increasing Subsequence) 18

674. 最长连续递增序列 674. Longest Continuous Increasing Subsequence 题目描述 给定一个未经排序的整型数组,找到最长且连续的递增序列. Given an unsorted array of integers, find the length of longest continuous increasing subsequence (subarray). 每日一算法2019/5/21Day 18LeetCode674. Longest Conti

LeetCode - 最长连续递增序列

题目描述: 给定一个未经排序的整数数组,找到最长且连续的的递增序列. 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3.尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开. 示例 2: 输入: [2,2,2,2,2] 输出: 1 解释: 最长连续递增序列是 [2], 长度为1. code: public class Solution { public int findLengthOfLCIS(i

最长单调递增子序列 POJ 3903 Stock Exchange .

题目传送门 : -------->点这里点这里<---------- 题目大意: 给出一串正整数,个数为N个.1<=N<=100000.求最长单调递增子序列长度. 样例输入: 6 5 2 1 4 5 3 3 1 1 1 4 4 3 2 1 样例输出: 3 1 1 =================================================================== 最长单调递增子序列问题的DP朴素算法复杂度为 O(n^2); 然而题目中的 N 最大有

HDURevenge of Segment Tree(第二长的递增子序列)

题目链接 题目大意:这题是求第二长的递增子序列. 解题思路:用n^2的算法来求LIS,但是这里还要记录一下最长的那个序列是否有多种组成方式,如果>= 2, 那么第二长的还是最长的LIS的长度,否则就是LIS - 1: 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1005; int l[maxn], c[maxn

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

得到最长连续递增序列

今天作死,看到别人发出来的笔试题就开干了,这tmd还理解错题目了,连续递增序列理解成上一个=下一个-1了. 这是我的成果,撸了4个多小时的: public class Test12 { public static void main(String[] args){ /** * 需求:找出最长的连续递增序列 * 步骤: * 1.找出所有连续序列可能结果,删除不是连续递增序列的,加入集合 * 2.集合排序,取第一个 * * 方式2: * 0.默认len为数组长度 * 1.找出数组中长度为len的序列

最长【递增】子序列:注意没有公共,即只有一个序列。

monotonic:单调的. 序列为X=(x1,x2,x3,x4...),首先排序X得到X',找出X和X'的最长公共子序列(LCS)即可. 另一种思维: 先回顾经典的O(n^2)的动态规划算法,设A[i]表示序列中的第i个数,F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设F[i] = 0 :(i = 1, 2, ..., len(A)).则有动态规划方程:F[i] = max{1, F[j] + 1} (j = 1, 2, ..., i - 1, 且A[j] < A[i])