hdu--3308 LCIS(线段树+区间合并)
Posted Wally的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu--3308 LCIS(线段树+区间合并)相关的知识,希望对你有一定的参考价值。
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].
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<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Output
For each Q, output the answer.
Sample Input
1 10 10 7 7 3 3 5 9 9 8 1 8 Q 6 6 U 3 4 Q 0 1 Q 0 5 Q 4 7 Q 3 5 Q 0 2 Q 4 6 U 6 10 Q 0 9
Sample Output
1 1 4 2 3 1 2 5
题意:给出一列n个数,进行m次操作,把第a的值变为b,查询[a,b]之间的最长连续上升子序列的长度,对于每个查询输出结果
思路:用线段树进行存当前节点的最大长度以及左边开始的长度和右边结束的长度,然后向上更新。查询时和线段树的查询一样,就是在查询时要注意对左右边界的更新。
AC代码:
1 #include<iostream> 2 #include<fstream> 3 #include<iomanip> 4 #include<cstdio> 5 #include<cstring> 6 #include<algorithm> 7 #include<cstdlib> 8 #include<cmath> 9 #include<set> 10 #include<map> 11 #include<queue> 12 #include<stack> 13 #include<string> 14 #include<vector> 15 #include<ctime> 16 #include<sstream> 17 #include<cassert> 18 using namespace std; 19 const int maxn=100005; 20 struct note 21 { 22 int l,r,lm,rm,m; 23 } a[maxn<<2]; 24 int p[maxn]; 25 int build(int l,int r,int k) 26 { 27 a[k].l=l; 28 a[k].r=r; 29 a[k].lm=a[k].rm=a[k].m=0; 30 if(l==r) 31 { 32 return 0; 33 } 34 int mid=(l+r)/2; 35 build(l,mid,k*2); 36 build(mid+1,r,k*2+1); 37 return 0; 38 } 39 int pushup(int k) 40 { 41 if(p[a[k*2].r]>=p[a[k*2+1].l]) 42 { 43 a[k].m=max(a[k*2].m,a[k*2+1].m); 44 a[k].lm=a[k*2].lm; 45 a[k].rm=a[k*2+1].rm; 46 } 47 else 48 { 49 a[k].m=max(max(a[k*2].rm+a[k*2+1].lm,a[k*2].m),a[k*2+1].m); 50 if(a[k*2].lm==(a[k*2].r-a[k*2].l+1)) 51 a[k].lm=a[k*2].lm+a[k*2+1].lm; 52 else 53 a[k].lm=a[k*2].lm; 54 if(a[k*2+1].rm==(a[k*2+1].r-a[k*2+1].l+1)) 55 a[k].rm=a[k*2].rm+a[k*2+1].rm; 56 else 57 a[k].rm=a[k*2+1].rm; 58 } 59 return 0; 60 } 61 int ins(int n,int d,int k) 62 { 63 if(a[k].l==a[k].r&&a[k].l==d) 64 { 65 a[k].rm=a[k].lm=a[k].m=1; 66 return 0; 67 } 68 if(a[k*2].r>=d) ins(n,d,k*2); 69 else if(a[k*2+1].l<=d) ins(n,d,k*2+1); 70 pushup(k); 71 return 0; 72 } 73 int sea(int l,int r,int k) 74 { 75 if(l==a[k].l&&a[k].r==r) 76 { 77 return a[k].m; 78 } 79 if(a[k*2].r>=r) return sea(l,r,k*2); 80 else if(a[k*2+1].l<=l) return sea(l,r,k*2+1); 81 else 82 { 83 int t1=sea(l,a[k*2].r,k*2); 84 int t2=sea(a[k*2+1].l,r,k*2+1); 85 int ans=max(t1,t2); 86 int sum=0; 87 if(p[a[k*2].r]<p[a[k*2+1].l]) 88 sum=min(a[k*2].r-l+1,a[k*2].rm)+min(r-a[k*2].r,a[k*2+1].lm); 89 return max(ans,sum); 90 } 91 } 92 int main() 93 { 94 int n,m,t,c,b; 95 scanf("%d",&t); 96 { 97 for(int kk=1; kk<=t; kk++) 98 { 99 scanf("%d%d",&n,&m); 100 build(1,n,1); 101 for(int i=1; i<=n; i++) 102 { 103 scanf("%d",&c); 104 p[i]=c; 105 ins(c,i,1); 106 } 107 char s[10]; 108 for(int i=0; i<m; i++) 109 { 110 scanf("%s",s); 111 if(s[0]==\'U\') 112 { 113 scanf("%d%d",&c,&b); 114 p[c+1]=b; 115 ins(b,c+1,1); 116 } 117 else 118 { 119 scanf("%d%d",&c,&b); 120 printf("%d\\n",sea(c+1,b+1,1)); 121 } 122 } 123 } 124 } 125 return 0; 126 }
以上是关于hdu--3308 LCIS(线段树+区间合并)的主要内容,如果未能解决你的问题,请参考以下文章