LightOJ 1277 Looking for a Subsequence

http://www.lightoj.com/volume_problemstat.php?problem=1277

  LightOJ搞得挺漂亮的,第一次到那里交题,挺喜欢的。

  线段树统计题,题意是:给出一行数,找到所要求的长度的单调上升子序列,并输出该序列。

  这题我是先从后往前,求出到达某个位置的时候,最长可以构建出多长的单调上升子序列。这是一个dp问题,不过用dp方法复杂度是O(n^2)会超时,所以我用线段树来降低查找的复杂度。题目比较简单,不过数据范围较大,所以要用hash来离散化处理。最后回溯一下就可以搜索出目标序列了!

代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <cstring>
  6 
  7 using namespace std;
  8 
  9 typedef vector<int> vi;
 10 const int hashSize = 400009;
 11 const int HASH = 0x55555555;
 12 int hash[hashSize], hashPos[hashSize];
 13 vi buf, X;
 14 
 15 void insHash(int x, int pos) {
 16     int p = (x ^ HASH) % hashSize;
 17 
 18     if (p < 0) p += hashSize;
 19     while (hash[p] != x && ~hashPos[p]) {
 20         p++;
 21         if (p >= hashSize) p -= hashSize;
 22     }
 23 
 24     hash[p] = x;
 25     hashPos[p] = pos;
 26 }
 27 
 28 int getPos(int x) {
 29     int p = (x ^ HASH) % hashSize;
 30 
 31     if (p < 0) p += hashSize;
 32     while (hash[p] != x && ~hashPos[p]) {
 33         p++;
 34         if (p >= hashSize) p -= hashSize;
 35     }
 36 
 37     return hashPos[p];
 38 }
 39 
 40 void initHash() {
 41     memset(hashPos, -1, sizeof(hashPos));
 42 }
 43 
 44 void scan(int &x) {
 45     char c;
 46 
 47     for ( ; ((c = getchar()) < '0' || c > '9') && c != '-'; ) ;
 48     if (c != '-') for (x = c - '0'; '0' <= (c = getchar()) && c <= '9'; x = x * 10 + c - '0') ;
 49     else for (x = 0; '0' <= (c = getchar()) && c <= '9'; x = x * 10 + '0' - c) ;
 50 }
 51 
 52 int treeSize;
 53 
 54 void input(int n) {
 55     int x;
 56 
 57     X.clear();
 58     buf.clear();
 59     initHash();
 60 
 61     while (n--) {
 62         scan(x);
 63         X.push_back(x);
 64         buf.push_back(x);
 65     }
 66     sort(X.begin(), X.end());
 67 
 68     int endi = unique(X.begin(), X.end()) - X.begin();
 69 
 70     treeSize = endi;
 71     for (int i = 0; i < endi; i++) {
 72         insHash(X[i], i);
 73     }
 74 }
 75 
 76 #define lson l, m, rt << 1
 77 #define rson m + 1, r, rt << 1 | 1
 78 #define ROOT 0, treeSize - 1, 1
 79 
 80 const int maxn = 100001;
 81 int mx[maxn << 2];
 82 
 83 void build(int l, int r, int rt) {
 84     mx[rt] = 0;
 85     if (l == r) return ;
 86 
 87     int m = (l + r) >> 1;
 88 
 89     build(lson);
 90     build(rson);
 91     mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
 92 }
 93 
 94 void update(int p, int x, int l, int r, int rt) {
 95     if (l == r) {
 96         mx[rt] = max(mx[rt], x);
 97         return ;
 98     }
 99     int m = (l + r) >> 1;
100 
101     if (p <= m) update(p, x, lson);
102     else update(p, x, rson);
103     mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
104 }
105 
106 int query(int L, int R, int l, int r, int rt) {
107     if (L <= l && r <= R) {
108         return mx[rt];
109     }
110     int m = (l + r) >> 1;
111 
112     if (L <= m) {
113         if (m < R) {
114             return max(query(L, R, lson), query(L, R, rson));
115         } else {
116             return query(L, R, lson);
117         }
118     }
119     if (m < R) {
120         return query(L, R, rson);
121     }
122 }
123 
124 int maxLen[maxn];
125 
126 void deal(int n, int m) {
127     input(n);
128     build(ROOT);
129     for (int i = n - 1; i >= 0; i--) {
130         int pos = getPos(buf[i]) + 1;
131 
132 //        printf("~%d\n", pos);
133         if (pos < treeSize) {
134             maxLen[i] = query(pos, treeSize - 1, ROOT) + 1;
135             update(pos - 1, maxLen[i], ROOT);
136         } else {
137             maxLen[i] = 1;
138             update(pos - 1, maxLen[i], ROOT);
139         }
140 //        printf("%d ", maxLen[i]);
141     }
142 //    puts("~~~");
143 
144     while (m--) {
145         int x, i = 0;
146 
147         scan(x);
148         while (i < n) {
149             if (maxLen[i] >= x) break;
150             i++;
151         }
152         if (i >= n) puts("Impossible");
153         else {
154             int last = buf[i];
155 
156             printf("%d", buf[i]);
157             x--;
158             i++;
159             while (x) {
160                 if (maxLen[i] >= x && buf[i] > last) {
161                     printf(" %d", buf[i]);
162                     x--;
163                     last = buf[i];
164                 }
165                 i++;
166             }
167             puts("");
168         }
169     }
170 }
171 
172 int main() {
173     int n, m;
174     int T;
175 
176 //    freopen("in", "r", stdin);
177     scan(T);
178     for (int i = 1; i <= T; i++) {
179         printf("Case %d:\n", i);
180         scan(n);
181         scan(m);
182         deal(n, m);
183     }
184 
185     return 0;
186 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/loj_1277_Lyon.html