51nod 1218 最长递增子序列 V2(dp + 思维)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1218

题解:先要确定这些点是不是属于最长递增序列然后再确定这些数在最长递增序列中出现的次数,如果大于1次显然是可能出现只出现1次肯定是必然出现。那么就是怎么判断是不是属于最长递增序列,这个只要顺着求一下最长递增标一下该点属于长度几然后再逆着求一下最长递减标一下该点属于长度几如果两个下标之和等于最长长度+1那么该点就属于最长递增序列,然后就是求1~len(len表示最长的长度)中各个长度出现的次数就行。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define inf 0X3f3f3f3f
using namespace std;
const int M = 5e4 + 10;
int a[M] , b[M] , dpa[M] , dpb[M] , vis[M];
bool vs[M];
int binsearch(int l , int r , int num) {
    int mid = (l + r) >> 1;
    int ans = 0;
    while(l <= r) {
        mid = (l + r) >> 1;
        if(b[mid] > num) r = mid - 1;
        else {
            ans = mid;
            l = mid + 1;
        }
    }
    return ans;
}
int binsearch2(int l , int r , int num) {
    int mid = (l + r) >> 1;
    int ans = 0;
    while(l <= r) {
        mid = (l + r) >> 1;
        if(b[mid] < num) r = mid - 1;
        else {
            ans = mid;
            l = mid + 1;
        }
    }
    return ans;
}
int main() {
    int n;
    scanf("%d" , &n);
    for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]);
    int len = 0;
    b[0] = -1;
    for(int i = 1 ; i <= n ; i++) {
        if(a[i] > b[len]) {
            len++;
            b[len] = a[i];
            dpa[i] = len;
            continue;
        }
        else {
            int pos = binsearch(1 , len , a[i]);
            b[pos + 1] = min(b[pos + 1] , a[i]);
            dpa[i] = pos + 1;
        }
    }
    int len2 = 0;
    memset(b , inf , sizeof(b));
    for(int i = n ; i >= 1 ; i--) {
        if(a[i] < b[len2]) {
            len2++;
            b[len2] = a[i];
            dpb[i] = len2;
        }
        else {
            int pos = binsearch2(1 , len2 , a[i]);
            b[pos + 1] = max(b[pos + 1] , a[i]);
            dpb[i] = pos + 1;
        }
    }
    memset(vs , false , sizeof(vs));
    for(int i = 1 ; i <= n ; i++) {
        if(dpa[i] + dpb[i] == len + 1) {
            vis[dpa[i]]++;
            vs[i] = true;
        }
    }
    printf("A:");
    for(int i = 1 ; i <= n ; i++) {
        if(vis[dpa[i]] > 1 && vs[i]) printf("%d " , i);
    }
    printf("\n");
    printf("B:");
    for(int i = 1 ; i <= n ; i++) {
        if(vis[dpa[i]] == 1 && vs[i]) printf("%d " , i);
    }
    printf("\n");
    return 0;
}
时间: 2024-10-02 23:45:47

51nod 1218 最长递增子序列 V2(dp + 思维)的相关文章

51nod 1376 最长递增子序列的数量(线段树)

51nod 1376 最长递增子序列的数量 数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个.例如A为:{1 3 2 0 4},1 3 4,1 2 4均为A的LIS.给出数组A,求A的LIS有多少个.由于数量很大,输出Mod 1000000007的结果即可.相同的数字在不同的位置,算作不同的,例如 {1 1 2} 答案为2. Input 第1行:1

[2016-05-11][51nod][1134 最长递增子序列]

时间:2016-05-11 14:16:50 星期三 题目编号:[2016-05-11][51nod][1134 最长递增子序列] 题目大意:给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 分析: 维护一个栈,如果是更大值,加入栈顶,否则,替换栈内第一个不小于它的数字 #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; co

51nod 1376: 最长递增子序列的数量(二维偏序+cdq分治)

1376 最长递增子序列的数量 Time Limit: 1 Sec Memory Limit: 128MB 分值: 160 难度:6级算法题 Description 数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个.例如A为:{1 3 2 0 4},1 3 4,1 2 4均为A的LIS.给出数组A,求A的LIS有多少个.由于数量很大,输出Mod 1

51nod 1134 最长递增子序列 (O(nlogn)算法)

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输

51nod 1134 最长递增子序列

给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输出最长递增子序列的长度. Input示例 8 5 1 6 8 2 4 5 10 Output示例 5 //第一种做法,放

LCS 51Nod 1134 最长递增子序列

给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输出最长递增子序列的长度. Input示例 8 5 1 6 8 2 4 5 10 Output示例 5 #include

51nod 1006 最长公共子序列Lcs(dp+string,无标记数组实现)

1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 取消关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列. Input 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) Output 输出最长的子序列,如果有多个,随意输出1个. Input示

51nod 1376 最长递增子序列的数量(不是dp哦,线段树 + &#160;思维)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 题解:显然这题暴力的方法很容易想到就是以每个数为结尾最长的有多少个,但是这样显然会超时所以要想一个方法去优化,要么用stl要么就是数据结构 线段树是个可以考虑的对象因为这也是求区间的和于是稍微将原数组优化一下,按照大小排序一下然后再按照下标更新这样能确保有序.具体看一下代码 还有一点要提一下有时候要考虑两维的东西可以适当排一下序使其变成一维有序这样就方

51NOD 1376 最长递增子序列的数量 dp+BIT

题目链接:点这里!! 题意:中文题 题解: f[i]:以第i个数结尾的LIS的长度,和该长度的LIS数量  转移的话,显然f[i].first=max{f[j].first}+1,j<i且a[j]<a[i]  f[i].second=∑jf[j].second,f[j].first=f[i].first−1  我们可以用BIT来优化这个转移,维护≤i的最大长度和对应数量 #include<bits/stdc++.h> using namespace std; #pragma com