Codeforces Round #277 (Div. 2) LIS of Sequence Dp

题意: 给出一个序列,问每个位置的元素,分别属于哪一类的东西。第一类 没有出现在任何的上升子序列中。 第三类 出现在所有上升子序列中 。第二类 就是剩下的了。。

求两个东西 ,  dp[i] 表示 从1到 i 最长上升子序列的长度,dp1[i]表示从i到n 最长上升子序列的长度。

设原序列最长上升子序列长度为len

1. 若dp[i]+dp1[i] - 1 != len , 他就属于第一类。

2. 若 t  = dp[i] 的 t 出现了不止一次,且不属于第一类,那他就是第二类。

剩下的就是第三类了。

代码写的有点戳。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<stdlib.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 111111;
vector<int> q[maxn];

int erfen(int a[], int l, int r, int key)
{
    int ans = -1;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (a[mid] >= key){
            ans = mid;
        }
        if (a[mid] >= key) r = mid - 1;
        else l = mid + 1;
    }
    return ans;
}


int erfen1(int a[], int l, int r, int key)
{
    int ans = -1;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (a[mid] <= key){
            ans = mid;
        }
        if (a[mid] <= key) r = mid - 1;
        else l = mid + 1;
    }
    return ans;
}
int a[maxn], a1[maxn];
int ans[maxn], ans1[maxn];
int dp[maxn], dp1[maxn];
int vis[maxn];
int main()
{
    int n;
    memset(vis, 0, sizeof(vis));
    int cnt = 0; int cnt1 = 0;
    scanf("%d", &n);
    for (int i = 0; i<n; i++)
        scanf("%d", &a[i]);
    ans[cnt++] = a[0]; dp[0] = 1;
    for (int i = 1; i<n; i++){
        int t = erfen(ans, 0, cnt - 1, a[i]);
        if (t == -1){
            ans[cnt++] = a[i]; dp[i] = cnt;
        }
        else{
            ans[t] = a[i];  dp[i] = t + 1;
        }
    }
    for (int i = 0; i<n; i++){
        a1[i] = a[n - i - 1];
    }
    cnt1 = 0;
    ans1[cnt1++] = a1[0]; dp1[0] = 1;
    for (int i = 1; i<n; i++){
        int t = erfen1(ans1, 0, cnt1 - 1, a1[i]);
        if (t == -1){
            ans1[cnt1++] = a1[i]; dp1[i] = cnt1;
        }
        else{
            ans1[t] = a1[i]; dp1[i] = t + 1;
        }
    }
    for (int i = 0; i<n / 2; i++) swap(dp1[i], dp1[n - i - 1]);
    for (int i = 0; i<n; i++){
        int t = dp[i] + dp1[i] - 1;
        if (t != cnt) vis[i] = 1;
    }
    for (int i = 0; i<n; i++){
        if (vis[i]) continue;
        q[dp[i]].push_back(i);
    }
    for (int i = 0; i<n; i++){
        int len = q[i].size();
        if (len <= 1) continue;
        for (int j = 0; j<len; j++){
            int t = q[i][j];
            vis[t] = 2;
        }
    }
    for (int i = 0; i<n; i++){
        if (!vis[i]) printf("3");
        else printf("%d", vis[i]);
    }
    cout << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/yigexigua/p/4097932.html