HDU 3308【线段树--c++版区间合并,dp】
2011-09-27 23:47
357 查看
LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 952 Accepted Submission(s): 447
[align=left]Problem Description[/align]
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].
[align=left]Input[/align]
T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).
[align=left]Output[/align]
For each Q, output the answer.
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
1 1 4 2 3 1 2 5
[align=left]Author[/align]
shǎ崽
[align=left]Source[/align]
HDOJ Monthly Contest – 2010.02.06
[align=left]Recommend[/align]
wxl
//题目:LCIS hdu 3308 //求任意长度的最长连续子序列,且随时会改变序列里面的值 #include <stdio.h> #include <memory.h> #include <iostream> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define Maxn 100100 using namespace std; int node[Maxn]; struct point { int Msum;//范围内的最大的长度 int lsum, rsum;//从最左端起最长的长度,从最右端起最长的长度 int lnum, rnum;//最左端的数字,最右端的数字 bool mark;//是否这一整段范围内的数都满足,即从左起的最大长度是整段的长度 void init() { Msum = lsum = rsum = mark = 1; } void PushUp(point, point); }pot[4 * Maxn]; inline int Max(int a, int b) { if(a > b) return a; return b; } void scan_d(int &a) { char in; in = getchar(); while( in != '-' && (in > '9' || in < '0')) { in = getchar(); } int mark = 0; if (in =='-') { mark = 1; a = 0; } else a = in - '0'; while (in = getchar(), in >= '0' && in <= '9') { a = a * 10 + in - '0'; } if (mark) a = -a; } void point::PushUp(point ls, point rs) {//合并ls,rs两个区间 lsum = ls.lsum; rsum = rs.rsum; lnum = ls.lnum; rnum = rs.rnum; Msum = Max(ls.Msum, rs.Msum); if (ls.rnum < rs.lnum) { if(ls.mark&&rs.mark) {//如果左右的区间都是全的那么父亲区间也要取全 Msum = lsum = rsum = lsum + rsum; mark = 1; return ; } mark = 0;//注意 if (ls.mark) lsum += rs.lsum; else if (rs.mark) rsum += ls.rsum; Msum = Max(Msum, rs.lsum + ls.rsum); } mark = 0;//注意 } void Build(int l, int r, int rt) { if (l == r) { pot[rt].init(); pot[rt].lnum = pot[rt].rnum = node[l];//注意是node[l] return ; } int m = (r + l) >> 1; Build(lson); Build(rson); pot[rt].PushUp(pot[rt<<1], pot[rt<<1|1]); } void UpDate(int a, int b, int l, int r, int rt) { if (l == r) { pot[rt].lnum = pot[rt].rnum = b; return ; } int m = (r + l) >> 1; if (a <= m) UpDate(a, b, lson); else UpDate(a, b, rson); pot[rt].PushUp(pot[rt<<1], pot[rt<<1|1]); } point query(int L, int R, int l, int r, int rt) { point ret; if (L > r || R < l) { ret.Msum = -1; return ret; } if (L <= l && R >= r) { return pot[rt]; } int m = (r + l) >> 1; point a = query(L, R, lson);//与c不一样的地方 point b = query(L, R, rson); if (a.Msum == -1) return b; if (b.Msum == -1) return a; ret.PushUp(a, b); return ret; } int main() { int casenumber, n, m, a, b; scan_d(casenumber); while (casenumber--) { scan_d(n); scan_d(m); for (int i = 1; i <= n; i++) scan_d(node[i]); Build(1, n, 1); char str; for (int i = 0; i < m; i ++) { str = getchar(); scan_d(a); scan_d(b); if (str == 'U') { UpDate(a + 1, b, 1, n, 1);//注意题目的范围是从0-n-1 } else { point h = query(a + 1, b + 1, 1, n, 1); printf("%d\n", h.Msum); } } } return 0; }
相关文章推荐
- HDU 3308 LCIS 最长上升字串(线段树区间合并)
- POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
- HDU 3308 线段树区间合并 + 单点修改
- hdu 3308 LCIS 最大连续递增字串长 线段树区间合并
- hdu 3308 LCIS(线段树区间合并)
- hdu 3308(线段树的区间合并)
- HDU 3308 LCIS 线段树的单点更新,区间合并
- hdu 3308(线段树区间合并)
- HDU - 3308 - LCIS (线段树 - 区间合并)
- HDU 3308 LCIS 线段树 区间合并 入门题
- (简单) HDU 3308 LCIS,线段树+区间合并。
- HDU 3308 LCIS (线段树合并区间)
- HDU 3308 LCIS(线段树区间合并)
- hdu 3308 线段树+区间合并
- 线段树区间合并+最长连续递增子序列——HDU 3308
- hdu 3308 LCIS(线段树单点更新+区间合并)中等难度的题目
- hdu 3308 LCIS(线段树区间合并)
- hdu 3308 线段树+区间合并
- hdu 3308-线段树基本区间合并
- HDU 3308 LCIS(线段树区间合并 单点更新)