ZOJ

来源:互联网 发布:js怎么设置left值 编辑:程序博客网 时间:2024/06/15 21:18

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2319

比赛链接:https://cn.vjudge.net/contest/158741#overview  密码:nyist


题目大意:首先输入一个数n,接下来是n行,每行两个数分别是Si、Bi;找尽可能多的人使他们不相互讨厌;


分析:相互讨厌:(Si<=Sj&&Bi>=Bj)or(Si>=Sj&&Bi<=Bj)根据这个条件,我们可以推断出当Si<Sj&&Bi<Bj时,满足这个条件找出的人才不相互讨厌。

那么要怎么找呢???是不是特别像最长单调递增子序列,就是这样。我们可以预处理一下(按Si从小到大排序,Bi从大到小排序),处理之后左端点就是单调递增的,这样我们找的时候就不用管了,在右端点中找最长单调递增子序列,找出来的结果就是我们要求的。


比赛的时候想到了最长单调递增子序列,但我们一直在想两个值同时递增怎么处理,虽然也排序预处理了,但还是没有想到直接找一个端点就行了。。。


Code:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<stdlib.h>#include<queue>using namespace std;const int maxn=100100;struct node{    int x,y,id;} c[maxn];bool cmp(node aa,node bb){    if(aa.x==bb.x)        return aa.y>bb.y;    else        return aa.x<bb.x;}int dp[maxn],ans[maxn],flag[maxn];int main(){    int t,n,T=0;    scanf("%d",&t);    while(t--)    {        if(T++)            printf("\n");        memset(ans,0,sizeof(ans));        memset(flag,0,sizeof(flag));        memset(dp,0,sizeof(dp));        scanf("%d",&n);        for(int i=0; i<n; i++)        {            scanf("%d%d",&c[i].x,&c[i].y);            c[i].id=i+1;        }        sort(c,c+n,cmp);        int len=0;        dp[++len]=c[0].y;        ans[0]=len;        for(int i=1; i<n; i++)        {           // cout<<len<<endl;            if(dp[len]<c[i].y)            {               // printf("%d***\n",c[i].y);                dp[++len]=c[i].y;                ans[i]=len;            }            else            {                int pos=lower_bound(dp+1,dp+len+1,c[i].y)-dp;                //二分右端点,找出c[i].y在dp数组中要更新的位置,并更新                //cout<<c[i].y<<" pos="<<pos<<endl;                dp[pos]=c[i].y;                ans[i]=pos;//记录当前点i属于上升子序列的第几个            }        }        int k=0;        printf("%d\n",len);        for(int i=n-1; i>=0; i--)        {            if(ans[i]==len)            {                //flag[k++]=ans[i];                flag[k++]=c[i].id;                len--;                if(!len)                    break;            }           // printf("%d ",ans[i]);        }        sort(flag,flag+k);        for(int i=0;i<k;i++)        {            if(i)                printf(" ");            printf("%d",flag[i]);        }        printf("\n");    }}

0 0
原创粉丝点击