• Gym 101246H ``North-East''(LIS)


    http://codeforces.com/gym/101246/problem/H

    题意:

    给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点。输出它可能经过的点和一定会经过的点。

    思路:

    分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走。

    观察一下,就可以发现这道题目就是要我们求一个LIS。

    首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面。

    用二分法求LIS,这样在d数组中就可以保存以第i个数结尾的LIS。

    求完之后,我们从后往前分析,如果当前点处于第x个位置(也就是LIS的第x个数),如果第x+1个位置的可走点的最大y值大于了当前点的y值,那么当前点是可以选的。在此过程中,动态维护LIS每个位置可走点的最大y值。当然了,还要记录每个位置可走点的个数(这个为第二个答案做铺垫,因为当一个点是可选的并且它所在的LIS位置上只有一个可走点,那么这个点肯定是要经过的)。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn=1e5+5;
    16 
    17 int n;
    18 
    19 struct Point
    20 {
    21     int x, y;
    22     int id;
    23     bool operator < (const Point& rhs) const
    24     {
    25         return x<rhs.x || (x==rhs.x && y>rhs.y);
    26     }
    27 }p[maxn];
    28 
    29 int g[maxn];
    30 int d[maxn];
    31 int h[maxn];
    32 
    33 int may[maxn];
    34 int cnt[maxn];
    35 
    36 vector<int> ans1, ans2;
    37 
    38 int main()
    39 {
    40     freopen("input.txt","r",stdin);
    41     freopen("output.txt","w",stdout);
    42     //freopen("in.txt","r",stdin);
    43     while(~scanf("%d",&n))
    44     {
    45         for(int i=1;i<=n;i++)
    46         {
    47             scanf("%d%d",&p[i].x, &p[i].y);
    48             p[i].id = i;
    49         }
    50 
    51         sort(p+1,p+n+1);
    52         int len = 0;
    53         for(int i=1;i<=n;i++)  g[i]=INF;
    54         for(int i=1;i<=n;i++)
    55         {
    56             int k=lower_bound(g+1,g+n+1,p[i].y)-g;
    57             if(k==len+1)  len++;
    58             d[i]=k;
    59             g[k]=p[i].y;
    60         }
    61 
    62         for(int i=1;i<=len;i++)  h[i]=-INF;
    63         memset(may,0,sizeof(may));
    64         memset(cnt,0,sizeof(cnt));
    65 
    66 
    67         for(int i=n;i>=1;i--)
    68         {
    69             int x=d[i];
    70             if(x==len)  {h[x]=max(h[x], p[i].y); may[i]=1; cnt[x]++;}
    71             else
    72             {
    73                 if(h[x+1]>p[i].y)  {h[x]=max(h[x],p[i].y); may[i]=1; cnt[x]++;}
    74             }
    75         }
    76 
    77         ans1.clear(); ans2.clear();
    78 
    79         for(int i=1;i<=n;i++)
    80             if(may[i])  ans1.push_back(p[i].id);
    81         sort(ans1.begin(),ans1.end());
    82         printf("%d ",ans1.size());
    83         for(int i=0;i<ans1.size();i++)
    84         {
    85             printf("%d%c",ans1[i],i==ans1.size()-1?'
    ':' ');
    86         }
    87 
    88         for(int i=1;i<=n;i++)
    89             if(may[i] && cnt[d[i]]==1)  ans2.push_back(p[i].id);
    90         sort(ans2.begin(),ans2.end());
    91         printf("%d ",ans2.size());
    92         for(int i=0;i<ans2.size();i++)
    93         {
    94             printf("%d%c",ans2[i],i==ans2.size()-1?'
    ':' ');
    95         }
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    python开源项目聚合推荐【1】
    python开发--Python实现延时操作的几种方式
    odoo开发笔记 -- 单台物理服务器上,利用docker部署多套odoo应用
    odoo开发笔记 -- odoo官方docker启动原理
    odoo开发笔记 -- odoo官方docker镜像部署
    odoo开发笔记 -- 借助模块queue_job实现异步方法调用
    odoo开发笔记 -- 提高访问安全性的一种方式
    python开发笔记-pymsslq连接操作SqlServer数据库
    运维笔记--Debian/Ubuntu系统离线安装pymssql,连接SqlServer
    python开发笔记-str转字典
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7074655.html
Copyright © 2020-2023  润新知