生活随笔
收集整理的這篇文章主要介紹了
hdu 3308 LCIS 线段树 + 区间合并
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
思路:
日常水一篇題解。
帶修改的求區間連續的遞增序列,我們考慮用線段樹維護。
直接維護mlenmlenmlen是區間最長的遞增序列,lslsls是從左端點開始的最長遞增序列,rsrsrs是從右端點開始的最長遞增序列,pushuppushuppushup的時候當且僅當左區間最右端的值小于右區間最左端的值的時候,兩端可以接起來,根據這個條件直接轉移就好啦。
我維護的信息有點多,其實本不需要維護最左和最右的值的。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=100010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
struct Node {int l
,r
;int val
;int mlen
,ls
,rs
,lval
,rval
;
}tr
[N
<<2];void pushup(int u
) {tr
[u
].lval
=tr
[L
].lval
;tr
[u
].rval
=tr
[R
].rval
;tr
[u
].mlen
=max(tr
[L
].mlen
,tr
[R
].mlen
);if(tr
[L
].ls
==Len(L
)) {if(tr
[L
].rval
<tr
[R
].lval
) tr
[u
].ls
=Len(L
)+tr
[R
].ls
;else tr
[u
].ls
=Len(L
);} else tr
[u
].ls
=tr
[L
].ls
;if(tr
[R
].rs
==Len(R
)) {if(tr
[R
].lval
>tr
[L
].rval
) tr
[u
].rs
=Len(R
)+tr
[L
].rs
;else tr
[u
].rs
=Len(R
);} else tr
[u
].rs
=tr
[R
].rs
;if(tr
[L
].rval
<tr
[R
].lval
) tr
[u
].mlen
=max(tr
[u
].mlen
,tr
[L
].rs
+tr
[R
].ls
);
}void build(int u
,int l
,int r
) {tr
[u
]={l
,r
};if(l
==r
) {scanf("%d",&tr
[u
].val
);tr
[u
].lval
=tr
[u
].rval
=tr
[u
].val
;tr
[u
].mlen
=tr
[u
].ls
=tr
[u
].rs
=1;return;}build(L
,l
,Mid
); build(R
,Mid
+1,r
);pushup(u
);
}void change(int u
,int pos
,int val
) {if(tr
[u
].l
==pos
&&tr
[u
].r
==pos
) {tr
[u
].val
=val
;tr
[u
].lval
=tr
[u
].rval
=tr
[u
].val
;return;}if(pos
<=Mid
) change(L
,pos
,val
);else change(R
,pos
,val
);pushup(u
);
}Node
query(int u
,int l
,int r
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) return tr
[u
];if(r
<=Mid
) return query(L
,l
,r
);else if(l
>Mid
) return query(R
,l
,r
);else {Node a
=query(L
,l
,r
),b
=query(R
,l
,r
);Node ans
;ans
.lval
=a
.lval
;ans
.rval
=b
.rval
;ans
.mlen
=max(a
.mlen
,b
.mlen
);if(a
.ls
==a
.r
-a
.l
+1) {if(a
.rval
<b
.lval
) ans
.ls
=a
.r
-a
.l
+1+b
.ls
;else ans
.ls
=a
.r
-a
.l
+1;} else ans
.ls
=a
.ls
;if(b
.rs
==b
.r
-b
.l
+1) {if(b
.lval
>a
.rval
) ans
.rs
=b
.r
-b
.l
+1+a
.rs
;else ans
.rs
=b
.r
-b
.l
+1;} else ans
.rs
=b
.rs
;if(a
.rval
<b
.lval
) ans
.mlen
=max(ans
.mlen
,a
.rs
+b
.ls
);return ans
;}
}int main()
{
int _
; scanf("%d",&_
);while(_
--) {scanf("%d%d",&n
,&m
);build(1,1,n
);while(m
--) {char op
[2]; int l
,r
; scanf("%s%d%d",op
,&l
,&r
);if(op
[0]=='U') l
++,change(1,l
,r
);else l
++,r
++,printf("%d\n",query(1,l
,r
).mlen
);}}return 0;
}
總結
以上是生活随笔為你收集整理的hdu 3308 LCIS 线段树 + 区间合并的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。