本题解仅用与作者加深算法理解,也欢迎大家的阅读

做题背景

原本关于二维的点的 \(dp\) 问题一直都没有什么想法,昨天晚上再做一道 \(cdq\) 的题目的时候被同学询问了这道题,发现可以用二维偏序使用的第一关键字排序,第二关键字用数据结构维护的方法来做,今天就把他切了。

题意

你需要从点 \((0,0)\) 走到点 \((n,n)\) ,且只能向右或向上走。同时给你 \(p\) 个点对 \((x_1,y_1),(x_2,y_2)\) ,满足 \(x_1 \leq x_2\) 且 \(y_1 \leq y_2\) 。如果你在中间走到了一个点对的第一个点,你可以立即达到第二点(不计算距离),问你行走的最小距离是多少。

题解

我们联想到用解决二维偏序的方法来做。

我们先根据点对的 \(x_1\) (第一关键词)和 \(y_1\) (第二关键词)来排序,这样的话我们的 \(dp\) 肯定是没有后效性的,然后易得,每一个点对的答案肯定得是从 \(x_1\) 前面的 \(y_2\) 比它小的点转移过来的,同时每个点可以更新的点是满足 \(x_2\) 后面的 \(y_1\) 比他大的点,这个东西是可以用树状数组来维护的。

( \(P.S.\) :\(y_1\) 作为第二关键词是因为会出现一些比较奇怪的点对,比如点对 \((0,0),(0,1)\) 和点对 \((0,2),(0,3)\) ,此时仅根据 \(x_1\) 排序肯定是不行的,可以再加一个第二关键词 \(y_1\) )

然后我们又发现,每一个点更新的顺序并不等于我们排序后的顺序(排序是根据 \(x_1\) ,更新是根据 \(x_2\) ),所以我们可以考虑用一个 \(set\) 来维护一下更新的时间顺序,到了相应的 \(x\) 轴位置再更新相应的点。

然后细节处理好就可以 \(AC\) 了,不要忘记离散化。

以上。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IT set<pair<int,int> >::iterator
const int N=1e5+5;
int n,maxn;
struct Board{int x1,y1,x2,y2,data;}s[N];
bool cmp(Board a,Board b)
{
if(a.x1!=b.x1)
return a.x1<b.x1;
return a.y1<b.y2;
};
map<int,int> mpx,mpy;
int ux[N<<1],sizex,uy[N<<1],sizey;
set<pair<int,int> > st;
struct TreeArray
{
int s[N<<1];
int lowbit(int x){return x&(-x);}
void updata(int k,int x){for(;k<(N<<1);k+=lowbit(k))s[k]=min(s[k],x);}
int query(int k){int res=1e18+7;for(;k;k-=lowbit(k))res=min(res,s[k]);return res;}
}t;
signed main()
{
cin>>maxn>>n;;
for(int i=1;i<=n;++i)
{
scanf("%lld%lld%lld%lld",&s[i].x1,&s[i].y1,&s[i].x2,&s[i].y2);
ux[++sizex]=s[i].x1,ux[++sizex]=s[i].x2;
uy[++sizey]=s[i].y1,uy[++sizey]=s[i].y2;
}
sort(s+1,s+1+n,cmp);
ux[++sizex]=0,ux[++sizex]=maxn;
uy[++sizey]=0,uy[++sizey]=maxn;
sort(ux+1,ux+1+sizex);
sort(uy+1,uy+1+sizey);
sizex=unique(ux+1,ux+1+sizex)-ux-1;
sizey=unique(uy+1,uy+1+sizey)-uy-1;
for(int i=1;i<=sizex;++i) mpx[ux[i]]=i;
for(int i=1;i<=sizey;++i) mpy[uy[i]]=i;
for(int i=1;i<=n;++i)
{
int tmp=mpx[s[i].x1];
for(IT j=st.begin();j!=st.end()&&j->first<=tmp;++j)
t.updata(mpy[s[j->second].y2],s[j->second].data-s[j->second].x2-s[j->second].y2);
while(!st.empty()&&st.begin()->first<=tmp) st.erase(st.begin());
s[i].data=t.query(mpy[s[i].y1])+s[i].x1+s[i].y1;
st.insert(make_pair(mpx[s[i].x2],i));
// printf("%d %d %d\n",s[i].x1,s[i].y1,s[i].data);
}
int tmp=mpx[maxn];
for(IT j=st.begin();j!=st.end()&&j->first<=tmp;++j)
t.updata(mpy[s[j->second].y2],s[j->second].data-s[j->second].x2-s[j->second].y2);
printf("%lld\n",t.query(mpy[maxn])+maxn+maxn);
return 0;
}

P6007 [USACO20JAN]Springboards G的更多相关文章

  1. Storyboards Tutorial 03

    这一节主要介绍segues,static table view cells 和 Add Player screen 以及 a game picker screen. Introducing Segue ...

  2. 文件图标SVG

    ​<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink ...

  3. 题解 P6005 【[USACO20JAN]Time is Mooney G】

    抢第一篇题解 这题的思路其实就是一个非常简单的dijkstra,如果跑到第一个点的数据不能更新的时候就输出 很多人不知道要跑多少次才停.其实这题因为答案要减去 T*c^2,而每条边的值 <= 1 ...

  4. [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...

  5. CentOS 6.6 升级GCC G++ (当前最新版本为v6.1.0) (完整)

    ---恢复内容开始--- CentOS 6.6 升级GCC G++ (当前最新GCC/G++版本为v6.1.0) 没有便捷方式, yum update....   yum install 或者 添加y ...

  6. Linux deepin 下sublimes配置g++ openGL

    参考 :http://blog.csdn.net/u010129448/article/details/47754623 ubuntu 下gnome只要将代码中deepin-terminal改为gno ...

  7. [翻译svg教程]svg 中的g元素

    svg 中的<g>元素用来组织svg元素.如果一组svg元素被g元素包裹了,你可以通过对g元素进行变换(transform),被g元素包裹的元素也将被变换,就好这些被svg包裹的元素是一个 ...

  8. 软件工程:黄金G点小游戏1.0

    我们要做的是黄金G点小游戏: N个同学(N通常大于10),每人写一个0~100之间的有理数 (不包括0或100),交给裁判,裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数),得到G值. ...

  9. 2016huasacm暑假集训训练五 G - 湫湫系列故事——减肥记I

    题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/G 这是一个01背包的模板题 AC代码: #include<stdio.h&g ...

随机推荐

  1. python中 try、except、finally 的执行顺序(转)

    def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') return 'try ...

  2. [LeetCode题解]876. 链表的中间结点 | 快慢指针

    解题思路 使用快慢指针.这里要注意的是,while 的条件会影响当中间节点有两个时,slow 指向的是第一个,还是第二个节点. // 返回的是第一个 while(fast.next != null & ...

  3. 关于重写equals同时重写hashcode

    1.Object中equals方法和hashcode public boolean equals(Object obj) { return (this == obj); } public native ...

  4. 03、MyBatis 映射文件

    1.XML映射器 2.select Select元素来定义查询操作 Id:唯一标识符 - 用来引用这条语句,需要和接口的方法名一致 parameterType:参数类型 - 可以不传,MyBatis会 ...

  5. Git本地仓库和远程仓库冲突解决

    场景描述: 在本地创建了一个git repo,并且执行了,git init命令,创建了.gitignore文件,或者README.md文件: 在远程创建了一个git repo,创建时也初始化了.git ...

  6. 写的太细了!Spring MVC拦截器的应用,建议收藏再看!

    Spring MVC拦截器 拦截器是Spring MVC中强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作. 拦截器概述 对于任何优秀的MVC框架, ...

  7. 解决Redis中数据不一致问题

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以马 ...

  8. python批量爬取猫咪图片

    不多说直接上代码 首先需要安装需要的库,安装命令如下 pip install BeautifulSoup pip install requests pip install urllib pip ins ...

  9. Java基础教程——枚举类型

    枚举类型 枚举类型在JDK 5时引入. enum WeekEnum { MONDAY, TUESDAY, WEDNESDAY, THURDAY, FRIDAY, SATURDAY, SUNDAY } ...

  10. eNSP VLAN划分基础配置及Access接口

    交换机内实现VLAN通信拓扑图: 一.修改主机名并保存 1.进入系统视图模式(配置模式) <Huawei>system-view 2.sysname命令修改主机名为yanyuda [Hua ...