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;
}
时间: 2024-10-26 13:59:45

Codeforces Round #277 (Div. 2) LIS of Sequence Dp的相关文章

Codeforces Round #277 (Div. 2) D. Valid Sets DP

D. Valid Sets As you know, an undirected connected graph with n nodes and n - 1 edges is called a tree. You are given an integer d and a tree consisting of n nodes. Each node i has a value ai associated with it. We call a set S of tree nodes valid if

Codeforces Round #277 (Div. 2)Valid Sets 树DP

题意:给出一棵树,并给出每个节点上的权值,求有多少个连通子块的最大值与最小值的差不超过d. 对于每个顶点建立一颗树,然后找比它价值大的   或者   价值相等且之前没有被当作顶点建立树的点,这样就避免重复了. dp[x]表示包涵x且以x为顶点的连通子树的个数,dp[x] = ∏ (dp[son[x]] + 1). 注意要用long long . #include<iostream> #include<iostream> #include<cstdio> #include

【codeforces】Codeforces Round #277 (Div. 2) 解读

门户:Codeforces Round #277 (Div. 2) 486A. Calculating Function 裸公式= = #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; LL n ; int main () { while ( ~scanf ( "%I64d" , &n )

贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation

题目传送门 1 /* 2 贪心+构造:因为是对称的,可以全都左一半考虑,过程很简单,但是能想到就很难了 3 */ 4 /************************************************ 5 Author :Running_Time 6 Created Time :2015-8-3 9:14:02 7 File Name :B.cpp 8 *************************************************/ 9 10 #include

Codeforces Round #277 (Div. 2) d

/**  * @brief Codeforces Round #277 (Div. 2) d  * @file d.cpp  * @author 面码  * @created 2014/11/17 14:53  * @edited  2014/11/17 14:53  * @type dfs dp  *   *  */ #include <cstdio> #include <vector> #define MOD 1000000007 #define MAXN 2014 using

Codeforces Round #277 (Div. 2) c

/**  * @brief Codeforces Round #277 (Div. 2) c  * @file c.c  * @author 面码  * @created 2014/11/14 13:39  * @edited  2014/11/14 13:39  * @type greedy  *  */ #include <stdio.h> #define MAXN 100010 #define MAXC 26 #define max(a, b)  ((a) > (b) ? (a) 

Codeforces Round #277 (Div. 2) a

/**  * @brief Codeforces Round #277 (Div. 2) a  * @author xiyan  * @created 2014/11/13 11:23  * @edited  2014/11/13 11:24  * @type math   *   *  */ #include <stdio.h> long long int a; int main() {     scanf("%I64d", &a);     printf(&qu

Codeforces Round #277 (Div. 2) b

/**  * @brief Codeforces Round #277 (Div. 2) b  * @author 面码  * @created 2014/11/13 14:01  * @edited  2014/11/13 14:01  * @type greedy  * @TODO less space and time cost with bitmap   *   *  */ #include <stdio.h> #define MAXN 110 //int a[MAXN][MAXN];

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with