Codeforces Gym101246H:``North-East''(LIS+思维)
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+思维)的更多相关文章
- Codeforces 583D. Once Again... (LIS变形)
题目链接:http://codeforces.com/contest/583/problem/D 给你t个长度为n的数组.问你最长不下降子序列的长度. 一开始用第一个n数组的lis和最后一个n数组的l ...
- Codeforces Zip-line 650D 345Div1D(LIS)
传送门 大意:给出一个序列,求修改一个数过后的最长上升子序列. 思路:可以用主席树在线搞,也可以用树状数组离线搞,明显后者好写得多.我们首先读取所有的询问,然后就把询问绑在给出的位置,然后我们正向做一 ...
- CodeForces - 427A (警察和罪犯 思维题)
Police Recruits Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Sub ...
- codeforces 895B XK Segments 二分 思维
codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...
- codeforces 893D Credit Card 贪心 思维
codeforces 893D Credit Card 题目大意: 有一张信用卡可以使用,每天白天都可以去给卡充钱.到了晚上,进入银行对卡的操作时间,操作有三种: 1.\(a_i>0\) 银行会 ...
- 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 ...
- hdu5256 二分求LIS+思维
解题的思路很巧,为了让每个数之间都留出对应的上升空间,使a[i]=a[i]-i,然后再求LIS 另外二分求LIS是比较快的 #include<bits/stdc++.h> #define ...
- C Alyona and Spreadsheet Codeforces Round #401(Div. 2)(思维)
Alyona and Spreadsheet 这就是一道思维的题,谈不上算法什么的,但我当时就是不会,直到别人告诉了我,我才懂了的.唉 为什么总是这么弱呢? [题目链接]Alyona and Spre ...
- codeforces 848B Rooter's Song 思维题
http://codeforces.com/problemset/problem/848/B 给定一个二维坐标系,点从横轴或纵轴垂直于发射的坐标轴射入(0,0)-(w,h)的矩形空间.给出点发射的坐标 ...
随机推荐
- [LeetCode OJ] Copy List with Random Pointer 扩大
职务地址:https://oj.leetcode.com/problems/copy-list-with-random-pointer/ 题意:对一个有回路的链表的深复制 解题:这道题我AC了之后才发 ...
- postgresql && .net core 使用空间数据
这里主要讲遇到的一些报错 增删改查 && 计算部分基本和sql server的空间数据操作一毛一样,感谢微软大大的倾情支持,直接看demo即可(- ̄▽ ̄)- 前往sql server ...
- WPF中的Application类。
原文:WPF中的Application类. Application对象用的名称空间是system.windows 1.手动创建Application对象步骤. 1.1).把项目中的App.Xaml文件 ...
- 数据库访问工具 DBUtl(公孙二狗)
数据库访问工具 DBUtil DBUtil 用于简化数据库的访问,只要准备好配置文件,调用 DBUtil 的静态函数就能直接得到查询数据库的结果. 本文主要内容有: 数据库访问的思考 DBUtil 实 ...
- WPF 过滤集合
<Window x:Class="ViewExam.MainWindow" xmlns="http://schemas.microsoft.com/w ...
- mysql数据库编码、字段编码、表编码 专题
CREATE DATABASE `mybatis-subject` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */ 其中的 ...
- WPF属性(一)依赖属性
原文:WPF属性(一)依赖属性 依赖属性是一种可以自己没有值,并能通过使用Binding从数据源获得值的属性,拥有依赖属性的对象称为依赖对象,在传统开发中,一个对象所占用的内存在调用new操作符进行实 ...
- LINQ查询表达式---------into
LINQ查询表达式---------into into 上下文关键字创建一个临时标识符,以便将 group.join 或 select 子句的结果存储到新的标识符 class Program { pu ...
- C# Lambda表达式Contains方法 like
原文:Lambda表达式Contains方法 like 1.使用Contains方法的必备条件: Contains等价于SQL中的like语句.不过Contains只针对于字符串(string)类型的 ...
- 安装 VirtualBox 出现回滚,无法安装及解决方法
原文:安装 VirtualBox 出现回滚,无法安装及解决方法 缘由:打算安装 Vagrant,因此打算安装 VirtualBox. 现象:安装 VirtualBox,进度快到最后的时候,安装程序执行 ...