首页 > 代码库 > HDU 3308 (线段树区间合并)

HDU 3308 (线段树区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3308

 

题意: 两个操作  : 1 修改 单点  a 处的值。

  2 求出 区间【a,b】内的最长上升子序列。

 

做法:线段树区间合并。了解线段树的具体含义很容易。

 

 1 // by caonima
 2 // hehe
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <cmath>
 8 using namespace std;
 9 const int MAX= 1e5+10;
10 int Lsum[MAX<<2],Rsum[MAX<<2],Msum[MAX<<2];
11 int Lnum[MAX<<2],Rnum[MAX<<2];
12 int a[MAX];
13 char Q[10];
14 
15 void push_up(int o,int m) {
16     Lsum[o]=Lsum[o<<1];
17     Rsum[o]=Rsum[o<<1|1];
18     Msum[o]=max(Msum[o<<1],Msum[o<<1|1]);
19     Lnum[o]=Lnum[o<<1];
20     Rnum[o]=Rnum[o<<1|1];
21     if(Rnum[o<<1]<Lnum[o<<1|1]) {
22         if(Lsum[o<<1]==(m-(m>>1))) Lsum[o]+=Lsum[o<<1|1];
23         if(Rsum[o<<1|1]==(m>>1)) Rsum[o]+=Rsum[o<<1];
24         Msum[o]=max(Msum[o],Rsum[o<<1]+Lsum[o<<1|1]);
25     }
26     return ;
27 }
28 
29 void build(int L,int R,int o) {
30     if(L==R) {
31         Lsum[o]=Rsum[o]=Msum[o]=1;
32         Lnum[o]=Rnum[o]=a[L];
33         return ;
34     }
35     int mid=(L+R)>>1;
36     build(L,mid,o<<1);
37     build(mid+1,R,o<<1|1);
38     push_up(o,R-L+1);
39 }
40 
41 void Update(int L,int R,int o,int k,int val) {
42     if(L==R) {
43         Lnum[o]=Rnum[o]=val;
44       //  Lsum[o]=Rsum[o]=Msum[o]=1;
45         return ;
46     }
47     int mid=(L+R)>>1;
48     if(k<=mid) Update(L,mid,o<<1,k,val);
49     else Update(mid+1,R,o<<1|1,k,val);
50     push_up(o,R-L+1);
51 }
52 
53 int Query(int L,int R,int o,int ls,int rs) {
54     if(ls<=L&&rs>=R) {
55         return Msum[o];
56     }
57     int mid=(L+R)>>1;
58     int ans=0;
59     if(ls<=mid) ans=max(ans,Query(L,mid,o<<1,ls,rs));
60     if(rs>mid) ans=max(ans,Query(mid+1,R,o<<1|1,ls,rs));
61     if(Rnum[o<<1]<Lnum[o<<1|1])
62     ans=max(ans,min(mid-ls+1,Rsum[o<<1])+min(rs-mid,Lsum[o<<1|1]));
63     return ans;
64 }
65 
66 int main() {
67     int cas,n,m,ls,rs;
68     scanf("%d",&cas);
69     while(cas--) {
70         scanf("%d %d",&n,&m);
71         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
72         build(1,n,1);
73         for(int i=1;i<=m;i++) {
74             scanf("%s %d %d",Q,&ls,&rs);
75             if(Q[0]==Q) {
76                 int res=Query(1,n,1,ls+1,rs+1);
77                 printf("%d\n",res);
78             }
79             else {
80                 Update(1,n,1,ls+1,rs);
81             }
82         }
83     }
84     return 0;

85 }