bzoj 4990(LCS->LIS)

来源:互联网 发布:数据更新维护机制 编辑:程序博客网 时间:2024/06/06 09:47

题意:上下有两个长度为n、位置对应的序列A、B,其中数的范围均为1~n。若abs(A[i]−B[j])<=4,则A[i]与B[j]间可以连一条边。现要求在边与边不相交的情况下的最大的连边数量。注意:保证A和B是全排列n≤1e5

思路:因为是全排列,所以类似大白书上的那个LCS转LIS的思想,记录下a中每个数字出现的位置,然后每读进来一个bi,就把[bi-4,bi+4]的每个合法的数字的位置保存下来,从大到小排个序,然后把n个bi的这个串串起来,最后的LIS就是答案。

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5 + 5;const int INF = 0x3f3f3f3f;int pos[maxn], dp[10 * maxn];int main(){    int n;    scanf("%d", &n);    for(int i = 1; i <= n; i++)    {        int x;        scanf("%d", &x);        pos[x] = i;    }    vector<int>num;    for(int i = 1; i <= n; i++)    {        int x;        scanf("%d", &x);        vector<int>vec;        for(int j = max(x-4, 1); j <= min(n, x + 4); j++)        {            vec.push_back(-pos[j]);        }        sort(vec.begin(), vec.end());        for(int i = 0; i < vec.size(); i++) num.push_back(-vec[i]);    }    memset(dp, INF, sizeof(dp));    for(int i = 0; i < num.size(); i++)    {        *lower_bound(dp, dp+num.size(), num[i]) = num[i];    }    printf("%d\n", lower_bound(dp, dp+num.size(), INF) - dp);    return 0;
原创粉丝点击