UVa 1471 Defense Lines - 线段树 - 离散化
题意是说给一个序列,删掉其中一段连续的子序列(貌似可以为空),使得新的序列中最长的连续递增子序列最长。
网上似乎最多的做法是二分查找优化,然而不会,只会值域线段树和离散化。。。
先预处理出所有的点所能延伸到最左端的长度,和到最右端的长度,然后离散化,然后对于当前的点,就交给值域线段树去查出前面最大的符合条件的向左延伸的长度,加上当前位置最大向右延伸的长度,更新答案即可。
Code
1 /** 2 * UVa 3 * Problem#1471 4 * Accepted 5 * Time:1190ms 6 */ 7 #include<iostream> 8 #include<cstdio> 9 #include<cctype> 10 #include<ctime> 11 #include<cstring> 12 #include<cstdlib> 13 #include<fstream> 14 #include<sstream> 15 #include<algorithm> 16 #include<map> 17 #include<set> 18 #include<stack> 19 #include<queue> 20 #include<vector> 21 #include<stack> 22 using namespace std; 23 typedef bool boolean; 24 #define inf 0xfffffff 25 #define smin(a, b) a = min(a, b) 26 #define smax(a, b) a = max(a, b) 27 template<typename T> 28 inline void readInteger(T& u){ 29 char x; 30 int aFlag = 1; 31 while(!isdigit((x = getchar())) && x != '-'); 32 if(x == '-'){ 33 x = getchar(); 34 aFlag = -1; 35 } 36 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 37 ungetc(x, stdin); 38 u *= aFlag; 39 } 40 41 typedef class SegTreeNode { 42 public: 43 int val; 44 SegTreeNode *l, *r; 45 SegTreeNode(int val = 0, SegTreeNode* l = NULL, SegTreeNode* r = NULL):val(val), l(l), r(r) { } 46 47 inline void pushUp() { 48 val = max(l->val, r->val); 49 } 50 }SegTreeNode; 51 52 typedef class SegTree { 53 public: 54 SegTreeNode* root; 55 SegTree():root(NULL) { } 56 SegTree(int s) { 57 build(root, 1, s); 58 } 59 60 void build(SegTreeNode*& node, int l, int r) { 61 node = new SegTreeNode(); 62 if(l == r) return; 63 int mid = (l + r) >> 1; 64 build(node->l, l, mid); 65 build(node->r, mid + 1, r); 66 } 67 68 void update(SegTreeNode*& node, int l, int r, int idx, int val) { 69 if(l == idx && r == idx) { 70 smax(node->val, val); 71 return; 72 } 73 int mid = (l + r) >> 1; 74 if(idx <= mid) update(node->l, l, mid, idx, val); 75 else update(node->r, mid + 1, r, idx, val); 76 node->pushUp(); 77 } 78 79 int query(SegTreeNode*& node, int l, int r, int ql, int qr) { 80 if(qr < ql) return -inf; 81 if(l == ql && r == qr) { 82 return node->val; 83 } 84 int mid = (l + r) >> 1; 85 if(qr <= mid) return query(node->l, l, mid, ql, qr); 86 if(ql > mid) return query(node->r, mid - 1, r, ql, qr); 87 int sl = query(node->l, l, mid, ql, mid); 88 int sr = query(node->r, mid + 1, r, mid + 1, qr); 89 return max(sl, sr); 90 } 91 92 inline void clear(SegTreeNode*& node) { 93 if(node == NULL) return; 94 clear(node->l); 95 clear(node->r); 96 delete[] node; 97 } 98 }SegTree; 99 100 int T; 101 int n; 102 int len; 103 int* lis; 104 int* buf; 105 SegTree st; 106 107 inline void init() { 108 readInteger(n); 109 lis = new int[(const int)(n + 1)]; 110 buf = new int[(const int)(n + 1)]; 111 for(int i = 1; i <= n; i++) 112 readInteger(lis[i]); 113 } 114 115 inline void descreate(int* a) { 116 memcpy(buf, a, sizeof(int) * (n + 1)); 117 sort(buf + 1, buf + n + 1); 118 len = unique(buf + 1, buf + n + 1) - buf; 119 for(int i = 1; i <= n; i++) 120 a[i] = lower_bound(buf + 1, buf + len, a[i]) - buf; 121 } 122 123 int *tol, *tor; 124 inline void dp() { 125 tol = new int[(const int)(n + 1)]; 126 tor = new int[(const int)(n + 1)]; 127 tol[1] = 1; 128 for(int i = 2; i <= n; i++) 129 tol[i] = (lis[i] > lis[i - 1]) ? (tol[i - 1] + 1) : (1); 130 tor[n] = 1; 131 for(int i = n - 1; i > 0; i--) 132 tor[i] = (lis[i] < lis[i + 1]) ? (tor[i + 1] + 1) : (1); 133 } 134 135 int result; 136 inline void solve() { 137 result = 1; 138 descreate(lis); 139 st = SegTree(len); 140 dp(); 141 // st.update(st.root, 1, len, lis[1], tol[1]); 142 for(int i = 1; i <= n; i++) { 143 int c = st.query(st.root, 1, len, 1, lis[i] - 1); 144 smax(result, c + tor[i]); 145 st.update(st.root, 1, len, lis[i], tol[i]); 146 } 147 printf("%d\n", result); 148 delete[] tol; 149 delete[] tor; 150 delete[] buf; 151 delete[] lis; 152 st.clear(st.root); 153 } 154 155 int main() { 156 readInteger(T); 157 while(T--) { 158 init(); 159 solve(); 160 } 161 return 0; 162 }