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

题意:在二维平面上有n个点,从最左下角的点出发,每次走只能走在当前的点的右上角的点(xj > xi, yj > yi)。问在走了最长路径的前提下有哪些点是可能被走到的,哪些点是必须被走到的。

思路:比赛的时候以为是图论的题目,结果可以转化为LIS求解,太强啦。

首先直接对坐标按照x从小到大进行排序,如果x相同,y从大到小排序。为什么y是从大到小排序呢?因为在后面我们只看y的大小来做LIS,即通过排序消掉了x维,那么如果x相同的话,y小的在前面会使长度变大,但是此时的x是相同的,并不满足题意要严格在右上角的要求,如果y大的在前面就不会使得长度变长了。因此是从大到小排序。

做LIS,是为了得到一个数组:h[i]代表i这个点的LIS的长度是多少。这样就可以直接求解了。观察下面这样一个样例。

(每次画图都是画得很恶心)

我们知道,假设要从3走到4,那么3的y必须严格小于后面的4的y的,否则这个点是不可能走的。

这样我们看图中,7、8两点的4肯定是由6号点的3贡献的,因为4、5号点的3的y是大于等于后面所有的4的。

这样我们可以逆向思维,从后往前扫,对于每个LIS的长度维护一个最大的y值,用一个maxh[]数组表示。设求得LIS最长长度为len,长度为len的所有点都可能走到,当扫到长度为len-1的时候,只有yi是小于maxh[len]才有可能走到,就这样扫到1。

还要解决哪些点必须走到,其实就是在可能走到的点里面,长度为h的点有且仅有一个的时候,这个点就必须走到,因为如果不走过这个点,就无法到达下一个长度为h+1的点了。

 #include <bits/stdc++.h>
using namespace std;
#define N 100010
struct node {
int x, y, id;
} p[N];
int n, len, h[N], maxh[N], dp[N], Hash[N];
vector<int> maybe, must; bool cmp(const node &a, const node &b) { if(a.x == b.x) return a.y > b.y; return a.x < b.x; } bool cp(const int &a, const int &b) { return p[a].id < p[b].id; } void LIS() { // 求解LIS
sort(p + , p + + n, cmp);
dp[] = p[].y; h[] = len = ;
for(int i = ; i <= n; i++) {
if(p[i].y > dp[len]) { dp[++len] = p[i].y; h[i] = len; }
int tmp = lower_bound(dp + , dp + + len, p[i].y) - dp;
dp[tmp] = p[i].y; h[i] = tmp;
}
} void solve() {
// 处理出哪些是可能的
for(int i = ; i <= n; i++) maxh[i] = -;
for(int i = n; i >= ; i--)
if(h[i] == len) { maxh[h[i]] = max(maxh[h[i]], p[i].y); maybe.push_back(i); }
else if(maxh[h[i]+] > p[i].y) { maxh[h[i]] = max(maxh[h[i]], p[i].y); maybe.push_back(i); }
// 处理出哪些是必须的
for(int i = ; i < maybe.size(); i++) Hash[h[maybe[i]]]++;
for(int i = ; i < maybe.size(); i++)
if(Hash[h[maybe[i]]] == ) must.push_back(maybe[i]); sort(maybe.begin(), maybe.end(), cp);
sort(must.begin(), must.end(), cp);
printf("%d ", maybe.size());
for(int i = ; i < maybe.size(); i++) printf("%d ", p[maybe[i]].id); puts("");
printf("%d ", must.size());
for(int i = ; i < must.size(); i++) printf("%d ", p[must[i]].id); puts("");
} int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d", &n);
for(int i = ; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y), p[i].id = i;
LIS();
solve();
return ;
}

Codeforces Gym101246H:``North-East''(LIS+思维)的更多相关文章

  1. Codeforces 583D. Once Again... (LIS变形)

    题目链接:http://codeforces.com/contest/583/problem/D 给你t个长度为n的数组.问你最长不下降子序列的长度. 一开始用第一个n数组的lis和最后一个n数组的l ...

  2. Codeforces Zip-line 650D 345Div1D(LIS)

    传送门 大意:给出一个序列,求修改一个数过后的最长上升子序列. 思路:可以用主席树在线搞,也可以用树状数组离线搞,明显后者好写得多.我们首先读取所有的询问,然后就把询问绑在给出的位置,然后我们正向做一 ...

  3. CodeForces - 427A (警察和罪犯 思维题)

    Police Recruits Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Sub ...

  4. codeforces 895B XK Segments 二分 思维

    codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...

  5. codeforces 893D Credit Card 贪心 思维

    codeforces 893D Credit Card 题目大意: 有一张信用卡可以使用,每天白天都可以去给卡充钱.到了晚上,进入银行对卡的操作时间,操作有三种: 1.\(a_i>0\) 银行会 ...

  6. C. Nice Garland Codeforces Round #535 (Div. 3) 思维题

    C. Nice Garland time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  7. hdu5256 二分求LIS+思维

    解题的思路很巧,为了让每个数之间都留出对应的上升空间,使a[i]=a[i]-i,然后再求LIS 另外二分求LIS是比较快的 #include<bits/stdc++.h> #define ...

  8. C Alyona and Spreadsheet Codeforces Round #401(Div. 2)(思维)

    Alyona and Spreadsheet 这就是一道思维的题,谈不上算法什么的,但我当时就是不会,直到别人告诉了我,我才懂了的.唉 为什么总是这么弱呢? [题目链接]Alyona and Spre ...

  9. codeforces 848B Rooter's Song 思维题

    http://codeforces.com/problemset/problem/848/B 给定一个二维坐标系,点从横轴或纵轴垂直于发射的坐标轴射入(0,0)-(w,h)的矩形空间.给出点发射的坐标 ...

随机推荐

  1. Java 阅读TXT文件

    public class GenCategoryAttrItemHandler { private final static String INPUT_FILE_PATH = "input/ ...

  2. Http请求格式(在Linux下使用telnet亲测,通过这篇我才明白)

    命令行窗口中用telnet测试HTTP协议请求消息格式响应消息格式1. 命令行窗口中用telnet测试HTTP协议 HTTP消息是由普通ASCII文本组成.消息包括消息头和数据体部分.消息头以行为单位 ...

  3. Qt5.8 下链接 Mysql 错误以及解决方法(无论 Mysql 是什么版本的,64 位 Qt 要用 64 位的 Mysql 驱动,32 位的 Qt 要用 32 位的Mysql 驱动)

    Qt 5.8 下链接 Mysql(Windows 平台下),有朋友会出现一个这个无法连接的错误 QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: ...

  4. ubuntu 关闭 phpmyadmin

    apache 有很多管理服务器的命令.apt-get installl phpmyadmin后突然想暂时关闭phpmyadmin,只需要a2disconf phpmyadmin即可.需要启用的时候再输 ...

  5. telerik ChartGrid浅谈

    在最近接触的项目中,有很多都是以Chart图表的方式呈现出来的,关于telerik Chart的使用,有几个小点跟大家分享一下. 1:本例子使用的Chart的命名空间为 xmlns:telerik=h ...

  6. C# 开机自动启动

    if (ConfigurationManager.AppSettings["IsBoot"].ToString().Trim().ToUpper() == "TRUE&q ...

  7. Win10《芒果TV - Preview》更新v3.1.31.0,全新播放页蜕变,预加载提速技术

    Win10<芒果TV - Preview>(商店内测版) v3.1.31.0 于2016年11月21日星期一晚上九点半登陆商店 主要是全面升级改造桌面播放页,新增观看互动评论.猜你喜欢功能 ...

  8. 我们错过了那么多机会,怎么办(就是预见未来的能力,并且要去做、要去投入,所以要主动学习、储备、选择,要不断的思考)good

    那天在IT职业咨询QQ群里聊天,提到腾讯.阿里,我说跟着这两家公司从小到大的朋友,都获得了不菲的回报,成了富翁或者财务自由了. 有群友感叹说:“是啊,我们错过了那么多机会.” 看到这句话,我心里一动, ...

  9. SignalR的简单实现(一)

    原文:SignalR的简单实现(一) ASP.NET SignalR是ASP.NET开发人员的一个新库,它使您的应用程序添加实时Web功能变得非常简单.什么是"实时网络"功能?能够 ...

  10. 利用shell脚本实现计划任务功能 V1.2

    2013.05.10  mytask 1.2 主程序休眠时间分成若干小的时间片断分段休眠,避免长时间的休眠不能及时响应系统信号. 2013.05.07 mytask 1.1 昨天发布了mytask1. ...