q種操作,查詢區間內最長連續上公升子串行的長度,或者修改某個點的值
線段樹維護:區間內最長連續上公升子串行的長度sub、區間內以左端點為起點的最長連續上公升子串行的長度lsub、區間內以右端點為終點的最長連續上公升子串行的長度rsub、區間左端點的值l和右端點的值r。
1#define io std::ios::sync_with_stdio(0);
2 #include 3
#define iter ::iterator
4using
namespace
std;
5 typedef long
long
ll;6 typedef pairp;
7#define pb push_back
8#define se second
9#define fi first
10#define rs o*2+1
11#define ls o*2
12const ll inf=0x7fffffff;13
const
int n=1e5+5;14
struct
nodea[n*4
];19
void pu(int o,int
len)
26 a[o].lsub=a[ls].lsub;
27if(a[ls].lsub==len-len/2&&a[rs].l>a[ls].r)
30 a[o].rsub=a[rs].rsub;
31if(a[o].rsub==len/2&&a[rs].l>a[ls].r)34}
35void build(int o,int l,int
r)43
int m=(l+r)/2;44
build(ls,l,m);
45 build(rs,m+1
,r);
46 pu(o,r-l+1
);47}48
void up(int o,int l,int r,int p,int
v)53
int m=(l+r)/2;54
if(p<=m)up(ls,l,m,p,v);
55else up(rs,m+1
,r,p,v);
56 pu(o,r-l+1
);57}58
int query(int o,int l,int r,int ql,int
qr)62
int m=(l+r)/2;63
int res=0;64
if(ql<=m)res=max(res,query(ls,l,m,ql,qr));
65if(qr>m)res=max(res,query(rs,m+1
,r,ql,qr));
66if(ql<=m&&qr>m&&a[ls].r69return
res;70}
71int
t,n,q;
72int
main()87}
88}89 }
HDU 3308 LCIS(線段樹合併)
維護乙個區間的包含最左的元素的lcis,包含最右元素的lcis,以及整個區間的lcis,然後pushup的時候就更新這三個值就行了。注意要考慮左右兒子可以 接 起來的情況等等 查詢的時候要注意,也要考慮左右可以 接 起來時候,不過還要注意,有可能左右兒子邊界的已經 越界了 就是超過了查詢範圍,還要取...
HDU 3308 LCIS(線段樹區間合併)
給你乙個序列,現在進行一些操作,一種是詢問某一段最長連續上公升子串行 lcis 的長度,另乙個就是修改某個點的值 區間合併的簡單題 這裡的區間合併,要判斷的是左兒子最右邊的值和右兒子最左邊的值的關係,那麼我們這道題要維護的東西就有 最左端開始的lcis,包括最右端的lcis,該區間的lcis,最左邊...
HDU 3308 LCIS 線段樹 區間合併
題目鏈結 前言 最近在做線段樹的練習,對於區間合併問題不是很清楚,花了好久才把線段樹的區間合併問題理清楚,所以把學習的過程記錄下來,建議手動建樹並模擬測試用例 題目大意 有乙個陣列,求這個陣列中最長的單調連續遞增序列的長度 題解 見一下注釋 樹結點的定義 有該結點的左端點 右端點 有該結點對應區間的...