ACdream 1216 (ASC训练1) Beautiful People(DP)

题目地址:http://acdream.info/problem?pid=1216

这题一开始用的是线段树,后来发现查询的时候还需要DP处理,挺麻烦。。也就不了了之了。。后来想到,这题其实就是一个二维的最长上升子序列。。

要先排序,先按左边的数为第一关键字进行升序排序,再按右边的数为第二关键字进行降序排序。这样的话,第一关键字相同的的肯定不在一个同一个上升子序列中。然后只对第二关键字进行复杂度为O(n*logn)的DP,找出最长上升序列,然后处理前驱,并输出即可。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL long long
struct node
{
    int x, y, num;
}fei[110000];
int cmp(node x, node y)
{
    if(x.x==y.x)
        return x.y>y.y;
    return x.x<y.x;
}
int a[110000], d[110000], pre[110000], len, b[110000];
int bin_seach(int x)
{
    int low=0, high=len, mid, ans;
    while(low<=high)
    {
        mid=low+high>>1;
        if(a[mid]>=x)
        {
            high=mid-1;
            ans=mid;
        }
        else
        {
            low=mid+1;
        }
    }
    return ans;
}
int main()
{
    int n, i, j, pos, cnt;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&fei[i].x,&fei[i].y);
            fei[i].num=i+1;
        }
        sort(fei,fei+n,cmp);
        len=1;
        a[1]=fei[0].y;
        d[0]=-1;
        d[1]=0;
        memset(pre,-1,sizeof(pre));
        for(i=1;i<n;i++)
        {
            if(fei[i].y>a[len])
            {
                a[++len]=fei[i].y;
                pre[i]=d[len-1];
                d[len]=i;
            }
            else
            {
                pos=bin_seach(fei[i].y);
                a[pos]=fei[i].y;
                pre[i]=d[pos-1];
                d[pos]=i;
            }
        }
        printf("%d\n",len);
        cnt=0;
        /*for(i=0;i<n;i++)
        {
            printf("%d ",fei[i].num);
        }
        puts("");*/
        for(i=d[len];i!=-1;i=pre[i])
        {
            b[cnt++]=fei[i].num;
            //printf("%d\n",i);
        }
        for(i=0;i<cnt-1;i++)
            printf("%d ",b[i]);
        printf("%d\n",b[cnt-1]);
    }
    return 0;
}
时间: 2024-08-22 23:44:17

ACdream 1216 (ASC训练1) Beautiful People(DP)的相关文章

二路单调自增子序列模型【acdream 1216】

题目:acdream 1216 Beautiful People 题意:每个人有两个值,能力值和潜力值,然后要求一个人的这两个值都严格大于第二个人的时候,这两个人才能呆在一块儿,给出许多人的值,求最多有多少个人? 分析:很容易想到是个单调非增模型,如果用O(n*n)的写法的话,会超时! 那么我们就要用二分优化来找. 我们可以先按第一个值 x 从小到大排序,然后按第二个值从大到小排序,这样的话找出的最长个数是没有错的.(想想为什么) 假如这样一个样例: 5 1 10 2 12 3 5 3 1 4

ACdream 1216——Beautiful People——————【二维LIS,nlogn处理】

Beautiful People Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description The most prestigious sports club in one city has exactly N members. Each of its members

ACdream 1216 Beautiful People(二维上升子序列 O(nlogn))

Beautiful People Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description The most prestigious sports club in one city has exactly N members. Each of its members

Problem D. What a Beautiful Lake dp

Problem D. What a Beautiful Lake Description Weiming Lake, also named "Un-named Lake", is the most famous scenic spot in Peking University. It is located in the north of the campus and is surrounded by walking paths, small gardens, and old red b

ASC(1)C(树形DP)

New Year Bonus Grant Special JudgeTime Limit: 6000/3000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description All programmers of Mocrosoft software company are organized in a strict subordination hi

ACdream 1083 有向无环图dp

题目链接:点击打开链接 人民城管爱人民 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 128000/64000 KB (Java/Others) SubmitStatistic Next Problem Problem Description 一天GG正在和他的后宫之中的一个的MM在外面溜达,MM突然说了一句,"我想吃鸡蛋灌饼"--当他们吃的正high的时候.城管出现了!作为传说中的最强军事力量,卖鸡蛋灌饼的小贩在他们面前也

【bzoj3387-跨栏训练】线段树+dp

我们可以想到一个dp方程:f[i][0]表示当前在i个栅栏的左端点,f[i][1]表示在右端点. 分两种情况: 第一种:假设现在要更新线段gh的左端点g,而它下来的路径被ef挡住了,那么必定是有ef来更新g. 为什么呢?因为其它点走到g必定要下落,比如说d到g,就相当于d到f再到g. 第二种:假设到ab的路径上没有东西挡着,那就可以直接从源点走过去再直接下落. 按照从上到下的顺序插入线段,线段树就是找当前的某个点被哪条id最大(也就是最低的)线段所覆盖. 1 #include<cstdio>

hiho一下 第五十八周 Beautiful String dp

题目1 : Beautiful String 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 We say a string is beautiful if it has the equal amount of 3 or more continuous letters (in increasing order.) Here are some example of valid beautiful strings: "abc", "cde"

SGU 199 Beautiful People(DP+二分)

时间限制:0.25s 空间限制:4M 题意: 有n个人,每个人有两个能力值,只有一个人的两个能力都小于另一个的能力值,这两个人才能共存,求能同时共存的最大人数. Solution: 显然这是一个两个关键字的最长上升序列. 先按照第一种能力值为第一关键字从小到大,第二能力值为第二关键字从大到小排序(为什么?) 然后就是直接用O(nlogn)的DP就好了 (排序的方法是根据O(nlogn)DP算法中所用到的辅助数组的性质...如果对这个算法理解足够的话应该比较容易想到) code(要用C++提交)