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. Token的设计(2)

    词法分析 Token的几个种类 前端的第一步就是词法分析, 这个过程通俗来讲就是将源代码转化为一串Tokens. 所以首先应该想到的是, 到底该有哪几种类型的Token ? 关于这个问题我已经想过了, ...

  2. Android Camera2拍照(一)——使用SurfaceView

    原文:Android Camera2拍照(一)--使用SurfaceView Camera2 API简介 Android 从5.0(21)开始,引入了新的Camera API Camera2,原来的a ...

  3. ubuntu16.04安装搜狗输入法

    安装完Ubuntu 16.04后,要更换为国内的软件源: Ali-OSM Alibaba Open Source Mirror Site Home About Join Us Ubuntu 1.软件包 ...

  4. NSLocalizedDescription=Request failed: unacceptable content-type: text/html 解决方法

    使用AFNetworking请求一个网站出现了以下错误 Error Domain=com.alamofire.error.serialization.response Code=- "Req ...

  5. 【转】编程之道 之 Rob Pike

    1.你无法断定程序会在什么地方耗费运行时间.瓶颈经常出现在想不到的地方,所以别急于胡乱找个地方改代码,除非你已经证实那儿就是瓶颈所在. 2.估量.在你没对代码进行估量,特别是没找到最耗时的那部分之前, ...

  6. C语言实现的CRC16/CCITT-FALSE校验码函数

    要求:输入字符串“00 AA FF CC AA 01 00” 得到校验码“79B1” 方法1: // ConsoleApplication1.cpp: 定义控制台应用程序的入口点. // #inclu ...

  7. delphi程序向另一个可执行程序发消息(使用GetForegroundWindow; 找出当前操作系统中活动的第一个窗口)

    function FindWindowThroughWindowText(WindowText: string): THandle;var  hCurrentWindow: THandle;  cnt ...

  8. Delphi的Anymouse方法探秘

    匿名函数是用Interface来实现的,具体细节可以看http://www.raysoftware.cn/?p=38匿名函数还是非常方便的.比如自己封装的异步调用.Async(procedure(AP ...

  9. Qt技术优势

    1. Qt这个C++的图形库由Trolltech在1994年左右开发.它可以运行在Windows,Mac OS X, Unix,还有像Sharp Zaurus这类嵌入式系统中.Qt是完全面向对象的. ...

  10. 为什么你有10年经验,但成不了专家?(重复性刻意训练+反馈修正,练习的精髓是要持续地做自己做不好的,太精彩了)真正的高手都有很强的自学能力,老师和教练的最重要作用是提供即时的反馈(莫非我从小到大学习不好的原因在这里?没有单独刻意训练?) good

    也许简单看书就是没有刻意训练.更没有反馈,所以没有效果 我倒是想起自己,研究VCL源码的时候,都是自己给自己提问,然后苦思冥想.自己解决问题,然后Windows编程水平果然上了一个台阶.对什么叫做“框 ...