[codevs4888零件分组][codevs1044拦截导弹]

codevs4888零件分组

两道题目都牵扯到了一个问题,一个区间中存在的单调序列的个数
若要求序列单调不增,则序列个数为最长单调递增序列;(导弹拦截)
若要求序列单调不减,则个数为最长单调递减序列;(零件分组)

证明摘自某不知名blog:

对于某序列有增有减,则该序列所形成的严格单调递增序列必然为其每个互相完全不相同单调递减序列的某一个元素共同构成,即对于序列100 68 66 56 78 89 66 20 9,其严格单调递增序列为56 78 89。显然56,78,89永远为三个不同的递减序列中的元素。
假如严格单调递增序列的元素不为不同的递减序列的元素。即某个递减序列贡献了多个元素为严格单调递增序列元素,那么显然这多个元素是单调递增的,与递减序列矛盾。即可证明。

即:单增序列中的每个元素一定不处于同意单减序列中,反之亦然

导弹拦截:

#include
#include
#include
#define INF 1061109567
using namespace std;
const int MAXN = 200000 + 50;
int n;
int A[MAXN],dp[MAXN],x;
int main()
{
    while(cin >> x)A[++ n] = x;
    for(int i = 1;i <= n;i ++)dp[i] = INF;
    for(int i = 1;i <= n;i ++){
        int loc = lower_bound(dp + 1,dp + n + 1,-A[i]) - dp;
        dp[loc] = -A[i];
    }
    int ans1 = lower_bound(dp + 1,dp + n + 1,INF) - dp - 1;
    for(int i = 1;i <= n;i ++){
        dp[i] = INF;
    }
    for(int i = 1;i <= n;i ++){
        int loc = lower_bound(dp + 1,dp + n + 1,A[i]) - dp;
        dp[loc] = A[i];
    }
    int ans2 = lower_bound(dp + 1,dp + n + 1,INF) - dp - 1;
    printf("%d\n%d",ans1,ans2);
    return 0;
}

零件分组:

#include
#include
#include
using namespace std;
struct edge
{
    int w,l;
}l[100010];
int n;
bool cmp(edge a,edge b)
{
    return a.w <= b.w;
}
int L[100010];
int dp[100010];
int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++)
    {
        scanf("%d%d",&l[i].w,&l[i].l);
    }
    sort(l + 1,l + n + 1,cmp);
    for(int i = 1;i <= n;i ++)L[i] = -l[i].l,dp[i] = 1061109567;
    for(int i = 1;i <= n;i ++)
    {
        int loc = lower_bound(dp + 1,dp + n + 1,L[i]) - dp;
        dp[loc] = L[i];
    }
    int ans = lower_bound(dp + 1,dp + n + 1,1061109567) - dp;
    printf("%d",ans - 1);
    return 0;
}

你可能感兴趣的:(模版/模型,====动态规划====,序列型)