team2012-F3-sol-0012

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
题意:有两组选手,每组n个人,并且给定n个可以胜利的对决,且双方必须按顺序出场,求最多能胜利多少场。
解法:这是一个最长单调子序列问题,由n的范围需要用nlogn的解法,设minend[i]为长度为i的单调子序列的最小结尾,则minend递增,二分查找并更新即可
}}}
{{{
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 100004;
int n, len, minend[MAXN], f[MAXN];

int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            int a, b;
            cin>>a>>b;
            f[a] = b;
        }
        len = 0;
        minend[0] = 0;
        for(int i=1;i<=n;i++)
        {
            minend[i] = MAXN;
            int loc = upper_bound(minend, minend+len+1, f[i]) - minend;
            if(loc == len+1)
                len++;
            if(minend[loc] > f[i])
                minend[loc] = f[i];
        }
        if(len*2 >= n)
            cout<<len<<endl;
        else
            cout<<-1<<endl;
    }
    return 0;
}
}}}
题意:有两组选手,每组n个人,并且给定n个可以胜利的对决,且双方必须按顺序出场,求最多能胜利多少场。
解法:这是一个最长单调子序列问题,由n的范围需要用nlogn的解法,设minend[i]为长度为i的单调子序列的最小结尾,则minend递增,二分查找并更新即可
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 100004;
int n, len, minend[MAXN], f[MAXN];
int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            int a, b;
            cin>>a>>b;
            f[a] = b;
        }
        len = 0;
        minend[0] = 0;
        for(int i=1;i<=n;i++)
        {
            minend[i] = MAXN;
            int loc = upper_bound(minend, minend+len+1, f[i]) - minend;
            if(loc == len+1)
                len++;
            if(minend[loc] > f[i])
                minend[loc] = f[i];
        }
        if(len*2 >= n)
            cout<<len<<endl;
        else
            cout<<-1<<endl;
    }
    return 0;
}