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?‘\n‘:‘ ‘);
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?‘\n‘:‘ ‘);
95         }
96     }
97     return 0;
98 }

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

时间: 2024-12-23 18:52:17

Gym 101246H ``North-East''(LIS)的相关文章

UVA - 10534Wavio Sequence(LIS)

题目:UVA - 10534Wavio Sequence(LIS) 题目大意:给出N个数字,找出这样的序列:2 * n + 1个数字组成.前面的n + 1个数字单调递增,后面n + 1单调递减. 解题思路:从前往后找一遍LIS,再从后往前找一遍LIS.最后只要i这个位置的LIS的长度和LDS的长度取最小值.再*2 - 1就是这个波浪数字的长度.注意这里的求LIS要用nlog(n)的算法,而且这里的波浪数字的对称并不是要求i的LIS == LDS,而是只要求LIS和LDS最短的长度就行了,长的那个

uva10723 - Cyborg Genes(LIS)

题目:uva10723 - Cyborg Genes(LIS) 题目大意:给出两个字符串,要求的到一个新的字符串,它保持了两个字符串的字符的特征,也就是可以在这个字符串中找到前两个字符串的子序列,求这样的字符串的最短长度和有多少种这样的不同的字符串. 解题思路:LIS.首先先要找出最长的公共子序列,这样得到的新的字符串的长度才会是最小:l1 + l2 - l[1][N]: l[i][j] :第一个字符串的前i个字符和第二个字符串的前j个字符的最长的公共子序列长度. n[i][j]: 使得第一个字

hoj_10001_朴素DP(LIS)

Longest Ordered Subsequence Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB Total submit users: 1937, Accepted users: 1621 Problem 10001 : No special judgement Problem description A numeric sequence of ai is ordered if a1 < a2 <

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

poj 3903 &amp; poj 2533 最长上升子序列(LIS)

最长上升子序列. 做这道题之前先做了2533,再看这道题,感觉两道题就一模一样,于是用2533的代码直接交, TLE了: 回头一看,数据范围.2533 N:0~1000:3903 N :1~100000. 原因终归于算法时间复杂度. 也借这道题学习了nlgn的最长上升子序列.(学习链接:http://blog.csdn.net/dangwenliang/article/details/5728363) 下面简单介绍n^2 和 nlgn 的两种算法. n^2: 主要思想:DP: 假设A1,A2..

BZOJ 1049 数字序列(LIS)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1049 题意:给出一个数列A,要求:(1)修改最少的数字使得数列严格递增:(2)在(1)的基础上使得修改的绝对值之和最小. 思路:对于第一问看起来像是求最长上升子 列,其实不是.我们想,若对于i<j,j能由i转移过来,那么需满足A[j]-A[i]>=j-i才行,这样我们发现只要A[j]-j& gt;=A[i]-i即可.因此令A[i]=A[i]-i,这样求LIS即可.对于第二问,

hoj_10027_优化DP(LIS)

Longest Ordered Subsequence Extention Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 778, Accepted users: 555 Problem 10027 : No special judgement Problem description A numeric sequence of ai is ordered if a1

HDU 5748 BestCoder Round #84 Bellovin (LIS)

Bellovin Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 540    Accepted Submission(s): 254 Problem Description Peter has a sequence a1,a2,...,an and he define a function on the sequence -- F

UVA10029 - Edit Step Ladders(LIS)

题目大意:UVA10029 - Edit Step Ladders(LIS) 题目大意:给你一个按照字典序读入的单词,然后要求你找出最长的序列,要求这个最长的序列也要满足字典序,并且后一个是由前一个单词,由在任意的地方替换,增加,删除一个字符变换来的. 解题思路:LIS.但是这里的O(n^2) 25000,超时.但是查找符合的单词有个规律,符合变换要求的单词的长度是有要求的,必须相差小于等于1.并且数据中相同长度的单词不会超过45个,那么就可以把这些单词按照长度分类,那么查找的时候就是45 *