您的位置:首页 > 其它

51nod1376 最长递增子序列的数量

2017-04-11 20:05 260 查看
这道题很sb,但是绝大多数人是用了高级数据结构的,我这里介绍一种(自己yy的)不需要高级数据结构的方法。

这道题不需要高级数据结构,考虑一开始的二分的方法,当我们们做到i时,我们维护的这个单调的序列的第j个位置表示的是

以min{A[x]},A[x]为原序列,其中以x结尾的LIS的长度为j.考虑在这个单调序列的每一个位置上开一个vector,表示出所有的x,容易发现,这个vector中x的A是单调不上升的。我们还可以再开一个vector记录方案数的前缀和,然后我们每次而二分到j这个位置时,再在j这个vector这里二分即可,就能找到当前加入点的以他结尾的lis的方案数

#include<cstdio>
#include<vector>
#include<algorithm>

using std :: vector;

const int N = 5e4 + 9, P = 1e9 + 7;

int n, A
, D
, tot, p, w, si
;
vector<int>G
, F
;

template<class T, bool cmp (int A, int B)> int lower_bound (T A, int l, int r, int x) {
int mid;
while (l <= r) {
mid = (l + r) >> 1;
if (cmp (A[mid], x)) r = mid - 1;
else l = mid + 1;
}
return l;
}

bool cmp1 (int A, int B) { return A >= B; }
bool cmp2 (int A, int B) { return A < B; }

void Add (int x) {
if (x > D[tot]) p = ++tot;
else p = lower_bound<int*, cmp1>(D, 1, tot, x);
D[p] = x;
if (p > 1) {
//      for (w = si[p - 1] - 1; ~w && G[p - 1][w] < x; --w) ; ++w;
w = lower_bound<const vector<int> &, cmp2> (G[p - 1], 0, si[p - 1] - 1, x);
w = (F[p - 1].back () - (w ? F[p - 1][w - 1] : 0)) % P;
} else {
w = 1;
}
//  if (x == 1e9 + 1) printf ("%d\n", (w + P) % P);
F[p].push_back ((w + (F[p].empty () ? 0 : F[p].back ())) % P);
G[p].push_back (x);
++si[p];
}

void IO () {
freopen ("1376.in", "r", stdin);
freopen ("1376.out", "w", stdout);
}

int main () {
//  IO ();
scanf ("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf ("%d", &A[i]);
Add (A[i]);
}
Add (1e9 + 1);
printf ("%d\n", (F[tot].back () + P) % P);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: