HDU - 3308 LCIS 题解

LCIS

Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8225 Accepted Submission(s): 3524


Problem 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].

Input
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).

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

Author
shǎ崽

Source
HDOJ Monthly Contest – 2010.02.06

题意:

两种操作,一种单点修改值,第二种查询区间最长连续上升子序列长度。

思路一:

用L[i]存储总体序列中以第i个位置结尾的LICS长度。用线段树维护这个L的区间最大值,更改i位置值的时候他会影响到L[i],以及i以后的一段区间,这段区间是连续上升的,我们可以二分求出这段区间,然后再线段树区间更改他。查询的时候需要特殊考虑查询区间的最长上升前缀,再线段树查询剩的区间的L最大值,复杂度m*(logn)^2。

  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21 
 22 using namespace std;
 23 
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define mp make_pair
 29 #define clr(a, x) memset(a, x, sizeof(a))
 30 
 31 const double pi = acos(-1.0);
 32 const int INF = 0x3f3f3f3f;
 33 const int MOD = 1e9 + 7;
 34 const double EPS = 1e-9;
 35 
 36 /*
 37 #include <ext/pb_ds/assoc_container.hpp>
 38 #include <ext/pb_ds/tree_policy.hpp>
 39 
 40 using namespace __gnu_pbds;
 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
 42 */
 43 
 44 int t, n, m, val[100015], L[100015];
 45 int Ma[400015], lazy[400015];
 46 void pushup(int i) {
 47     Ma[i] = max(Ma[i << 1], Ma[i << 1 | 1]);
 48 }
 49 void pushdown(int i) {
 50     if (lazy[i]) {
 51         Ma[i << 1] += lazy[i];
 52         Ma[i << 1 | 1] += lazy[i];
 53         lazy[i << 1] += lazy[i];
 54         lazy[i << 1 | 1] += lazy[i];
 55         lazy[i] = 0;
 56     }
 57 }
 58 void build(int i, int l, int r) {
 59     lazy[i] = 0;
 60     if (l == r) {
 61         Ma[i] = L[l];
 62         return;
 63     }
 64     int mi = l + r >> 1;
 65     build(i << 1, l, mi);
 66     build(i << 1 | 1, mi + 1, r);
 67     pushup(i);
 68 }
 69 void update(int i, int l, int r, int x, int y, int z) {
 70     if (x <= l && r <= y) {
 71         Ma[i] += z;
 72         lazy[i] += z;
 73         return;
 74     }
 75     pushdown(i);
 76     int mi = l + r >> 1;
 77     if (x <= mi) update(i << 1, l, mi, x, y, z);
 78     if (mi < y) update(i << 1 | 1, mi + 1, r, x, y, z);
 79     pushup(i);
 80 }
 81 int query(int i, int l, int r, int x, int y) {
 82     if (x <= l && r <= y) {
 83         return Ma[i];
 84     }
 85     pushdown(i);
 86     int res1 = 0, res2 = 0, mi = l + r >> 1;
 87     if (x <= mi) res1 = query(i << 1, l, mi, x, y);
 88     if (mi < y) res2 = query(i << 1 | 1, mi + 1, r, x, y);
 89     return max(res1, res2);
 90 }
 91 //#define local
 92 int main() {
 93 #ifdef local
 94     freopen("data.in", "r", stdin);
 95     freopen("data.out", "w", stdout);
 96 #endif // local
 97     scanf("%d", &t);
 98     val[0] = -1, L[0] = 0;
 99     while (t--) {
100         scanf("%d%d", &n, &m);
101         for (int i = 1; i <= n; ++i) {
102             scanf("%d", &val[i]);
103             if (val[i] > val[i - 1]) {
104                 L[i] = L[i - 1] + 1;
105             } else {
106                 L[i] = 1;
107             }
108         }
109         build(1, 1, n);
110         while (m--) {
111             char op;
112             int a, b;
113             scanf(" %c %d%d", &op, &a, &b);
114             if ('U' == op) {
115                 ++a;
116                 L[a] = query(1, 1, n, a, a);
117                 int pre_l = L[a], pre_v = val[a];
118                 val[a] = b;
119                 if (a > 1) {
120                     L[a - 1] = query(1, 1, n, a - 1, a - 1);
121                 }
122                 L[a] = (val[a] > val[a - 1] ? L[a - 1] + 1 : 1);
123                 update(1, 1, n, a, a, L[a] - pre_l);
124                 if (a == n) continue;
125                 int s = a + 1, e = n, mi, pos;
126                 L[a + 1] = query(1, 1, n, a + 1, a + 1);
127                 while (s <= e) {
128                     mi = s + e >> 1;
129                     L[mi] = query(1, 1, n, mi, mi);
130                     if (L[mi] - L[a + 1] == mi - a - 1) {
131                         s = (pos = mi) + 1;
132                     } else {
133                         e = mi - 1;
134                     }
135                 }
136                 if (pre_v < val[a + 1] && val[a] >= val[a + 1]) {
137                     update(1, 1, n, a + 1, pos, -pre_l); // pre_l换成 L[a] 不对
138                 } else if (pre_v >= val[a + 1] && val[a] < val[a + 1]) {
139                     update(1, 1, n, a + 1, pos, L[a]);
140                 } else if (val[a] < val[a + 1]) {
141                     update(1, 1, n, a + 1, pos, L[a] - pre_l);
142                 }
143             } else {
144                 ++a, ++b;
145                 int s = a, e = b, mi, pos1 = b + 1, pos2 = a - 1;
146                 L[a] = query(1, 1, n, a, a);
147                 while (s <= e) {
148                     mi = s + e >> 1;
149                     L[mi] = query(1, 1, n, mi, mi);
150                     if (mi - a == L[mi] - L[a]) {
151                         s = mi + 1;
152                     } else {
153                         e = (pos1 = mi) - 1;
154                     }
155                 }
156                 int ans = pos1 - a;
157                 if (pos1 <= b) {
158                     int res = query(1, 1, n, pos1, b);
159                     ans = max(ans, res);
160                 }
161                 printf("%d\n", ans);
162             }
163         }
164     }
165     return 0;
166 }
167 /*
168 2
169 10 6
170 1 3 6 2 7 4 3 5 6 6
171 Q 0 9
172 U 2 1
173 Q 1 4
174 U 5 1
175 Q 2 8
176 Q 5 7
177 */

 思路二:

刚学习到这是一类经典的线段树区间合并问题。线段树节点可以维护三个值,区间内最大连续子串,包含左端点的最大连续子串,包含右端点的最大连续子串,pushup向上维护父节点信息的时候都可以通过这三个值维护出来,同时对query函数做几乎一样的分类讨论处理就行了,复杂度mlogn。

  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21 
 22 using namespace std;
 23 
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define mp make_pair
 29 #define clr(a, x) memset(a, x, sizeof(a))
 30 
 31 const double pi = acos(-1.0);
 32 const int INF = 0x3f3f3f3f;
 33 const int MOD = 1e9 + 7;
 34 const double EPS = 1e-9;
 35 
 36 /*
 37 #include <ext/pb_ds/assoc_container.hpp>
 38 #include <ext/pb_ds/tree_policy.hpp>
 39 
 40 using namespace __gnu_pbds;
 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
 42 */
 43 
 44 int t, n, m, val[100015];
 45 struct node {
 46     int Ma, Ma_l, Ma_r;
 47     node () {}
 48     node (int Ma, int Ma_l, int Ma_r) : Ma(Ma), Ma_l(Ma_l), Ma_r(Ma_r) {}
 49 } Node[400015];
 50 void pushup(int i, int l, int r) {
 51     int mi = l + r >> 1, lson = i << 1, rson = i << 1 | 1;
 52     Node[i].Ma_l = Node[lson].Ma_l;
 53     Node[i].Ma_r = Node[rson].Ma_r;
 54     Node[i].Ma = max(Node[lson].Ma, Node[rson].Ma);
 55     if (val[mi] < val[mi + 1]) {
 56         if (Node[lson].Ma_l == mi - l + 1) {
 57             Node[i].Ma_l = Node[lson].Ma_l + Node[rson].Ma_l;
 58         }
 59         if (Node[rson].Ma_r == r - mi) {
 60             Node[i].Ma_r = Node[rson].Ma_r + Node[lson].Ma_r;
 61         }
 62         Node[i].Ma = max(Node[i].Ma, Node[lson].Ma_r + Node[rson].Ma_l);
 63     }
 64 }
 65 void build(int i, int l, int r) {
 66     if (l == r) {
 67         Node[i] = node(1, 1, 1);
 68         return;
 69     }
 70     int mi = l + r >> 1;
 71     build(i << 1, l, mi);
 72     build(i << 1 | 1, mi + 1, r);
 73     pushup(i, l, r);
 74 }
 75 void update(int i, int l, int r, int p, int z) {
 76     if (l == r) {
 77         val[l] = z;
 78         return;
 79     }
 80     int mi = l + r >> 1;
 81     if (p <= mi) update(i << 1, l, mi, p, z);
 82     if (mi < p) update(i << 1 | 1, mi + 1, r, p, z);
 83     pushup(i, l, r);
 84 }
 85 node query(int i, int l, int r, int x, int y) {
 86     if (x <= l && r <= y) {
 87         return Node[i];
 88     }
 89     int mi = l + r >> 1;
 90     node ans, res1, res2;
 91     ans = res1 = res2 = node(0, 0, 0);
 92     if (x <= mi) res1 = query(i << 1, l, mi, x, y);
 93     if (mi < y) res2 = query(i << 1 | 1, mi + 1, r, x, y);
 94     ans.Ma = max(res1.Ma, res2.Ma);
 95     ans.Ma_l = res1.Ma_l, ans.Ma_r = res2.Ma_r;
 96     if (x <= mi && mi < y && val[mi] < val[mi + 1]) {
 97         ans.Ma = max(ans.Ma, res1.Ma_r + res2.Ma_l);
 98         if (res1.Ma_l == mi - l + 1) {
 99             ans.Ma_l = res1.Ma_l + res2.Ma_l;
100         }
101         if (res2.Ma_r == r - mi) {
102             ans.Ma_r = res1.Ma_r + res2.Ma_r;
103         }
104     }
105     return ans;
106 }
107 void print() {
108     for (int i = 1; i <= n << 2; ++i) {
109         printf("Node[%d].Ma = %d, Ma_l = %d, Ma_r = %d ", i, Node[i].Ma, Node[i].Ma_l, Node[i].Ma_r);
110         if (i % 2 == 0) puts("");
111     }
112     for (int i = 1; i <= n; ++i) printf("%d ", val[i]);
113     puts("");
114 }
115 int main() {
116     scanf("%d", &t);
117     while (t--) {
118         scanf("%d%d", &n, &m);
119         for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
120         build(1, 1, n);
121         while (m--) {
122             char op;
123             int x, y;
124             scanf(" %c%d%d", &op, &x, &y);
125             if ('U' == op) {
126                 update(1, 1, n, ++x, y);
127             } else {
128                 printf("%d\n", query(1, 1, n, ++x, ++y).Ma);
129             }
130         }
131     }
132     return 0;
133 }

废话:最近的代码总坑在几处细微甚至不该错的地方,而且好久都调不出来,最近确实有些累了,状态不太好,更主要的还是练得不够呀...

转载于:https://www.cnblogs.com/BIGTOM/p/8493581.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值