题目大意:

给定平面上的一些点,求这些点的一个\(LIS\),并且还需要满足下列式子最小:

\[\sum_{i=1}^{n-1}(a[i+1].x-a[i].x)*(a[i+1].y-a[i].y)
\]

题解:

比较巧妙的一道题。

首先我们需要找出一个性质,我们先令\(dp[i]\)表示以\(i\)点结尾的\(LIS\),然后这些\(LIS\)相同的点在平面上是横坐标递增,纵坐标递减的,下面我们说的转移点的顺序都是按照这个顺序来的。

然后我们在观察转移,我们令两个转移点\(j\)和\(k\),若\(k\)比\(j\)更优,那么有:

\[dp[k]+(a[i].x-a[k].x)*(a[i].y-a[k].y)\geq dp[j]+(a[i].x-a[j].x)*(a[i].y-a[j].y)
\]

\[a[i].x*(a[j].y-a[k].y)+a[i].y*(a[j].x-a[k].x)\geq dp[j]-dp[k]+a[j].x*a[j].y-a[k].x*a[k].y
\]

\[A*a[i].x+B*a[i].y\geq C
\]

可以看出,这其实是一个半平面,结合上面的性质,对于一排待转移点,更优的转移是一段前缀或者一段后缀,这启发我们这道题中有决策单调性。

但是这个东西还有一个条件就是\(a[i].x\geq a[j].x\ \ a[i].y\geq a[j].y\),这个东西其实我们发现合法的转移点也是一段连续的区间,这启发我们在外面线段树分治解决这个限制。

对于决策单调性的部分,我们可以令\(k\)是\(j\)的后面一个点,那么上面的\(A\)是负的\(B\)是正的,所以合法的区域在直线上方,按照这个做决策单调性就好了。

代码

#include<bits/stdc++.h>
#define M 1000009
#define N 200009
using namespace std;
typedef long long ll;
vector<int>vec[N],now;
vector<int>::iterator it;
int n,T,dp[N];
ll f[N],ans;
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct BIT{
int tr[M];
inline void add(int x,int y){
while(x<=T)tr[x]=max(tr[x],y),x+=x&-x;
}
inline int query(int x){
int ans=0;
while(x)ans=max(ans,tr[x]),x-=x&-x;
return ans;
}
}T1;
struct point{
int x,y;
inline bool operator <(const point &b)const{
if(x!=b.x)return x<b.x;
else return y<b.y;
}
}a[N];
struct seg{
#define ls tr[cnt].l
#define rs tr[cnt].r
int rot,tott;
struct node{
int l,r;
vector<int>nw;
}tr[N<<1];
void build(int &cnt,int l,int r){
cnt=++tott;tr[cnt].l=tr[cnt].r=0;
tr[cnt].nw.clear();
if(l==r)return;
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
inline void init(){
tott=0;
build(rot,0,now.size()-1);
}
inline void upd(int cnt,int l,int r,int id){
if(a[id].x>=a[now[r]].x&&a[id].y>=a[now[l]].y){
tr[cnt].nw.push_back(id);
return;
}
if(a[id].x<a[now[l]].x||a[id].y<a[now[r]].y)return;
if(l==r)return;
int mid=(l+r)>>1;
upd(ls,l,mid,id);upd(rs,mid+1,r,id);
}
inline void _upd(int tag,int l,int r,int L,int R){
if(l>r)return;
int no=tr[tag].nw[(l+r)>>1];
ll biu=1e18,tg=0;
for(int i=L;i<=R;++i){
int id=now[i];
ll x=f[id]+1ll*(a[no].x-a[id].x)*(a[no].y-a[id].y);
if(x<biu){
biu=x;
tg=i;
}
}
f[no]=min(f[no],biu);
int mid=(l+r)>>1;
_upd(tag,l,mid-1,tg,R);
_upd(tag,mid+1,r,L,tg);
}
inline void work(int id){
upd(rot,0,now.size()-1,id);
}
void solve(int cnt,int l,int r){
_upd(cnt,0,tr[cnt].nw.size()-1,l,r);
if(l==r)return;
int mid=(l+r)>>1;
solve(ls,l,mid);solve(rs,mid+1,r);
}
inline void solve(){
solve(rot,0,now.size()-1);
}
#undef ls
#undef rs
}T2;
int main(){
n=rd();T=rd();
for(int i=1;i<=n;++i){
a[i].x=rd();a[i].y=rd();
}
sort(a+1,a+n+1);
int maxx=0;
for(int i=1;i<=n;++i){
dp[i]=T1.query(a[i].y)+1;
T1.add(a[i].y,dp[i]);
vec[dp[i]].push_back(i);
maxx=max(maxx,dp[i]);
}
memset(f,0x3f,sizeof(f));
for(it=vec[1].begin();it!=vec[1].end();++it){
int x=*it;
f[x]=1ll*a[x].x*a[x].y;
}
for(int i=2;i<=maxx;++i){
now=vec[i-1];
T2.init();
for(it=vec[i].begin();it!=vec[i].end();++it){
int x=*it;
T2.work(x);
}
T2.solve();
}
ans=1e18;
for(it=vec[maxx].begin();it!=vec[maxx].end();++it){
int x=*it;
ans=min(ans,f[x]+1ll*(T-a[x].x)*(T-a[x].y));
}
cout<<ans;
return 0;
}

[USACO19FEB]Mowing Mischief的更多相关文章

  1. 解题报告:luogu P5543 [USACO19FEB]The Great Revegetation S

    题目链接:P5543 [USACO19FEB]The Great Revegetation S 好坑啊,都身败名裂了. 思路一: 考虑染色法,跑一遍搜所就好了,不给代码了. 思路二: 考虑并查集,我想 ...

  2. P2034 选择数字 / P2627 [USACO11OPEN]Mowing the Lawn G

    Link 题目描述 给定一行 \(n\) 个非负整数 \(a[1]..a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入 ...

  3. [USACO19FEB]Moorio Kart

    题目 我们的神仙教练在考试里放了这道题,当时我非常惊讶啊 背包是\(O(n^3)\)的吧明明是带根号的好吧,那既然要优化的话 NTT!什么时候我们教练会在考试里放多项式了 模数\(1e9+7\)? 任 ...

  4. P5242 [USACO19FEB]Cow Dating

    题目链接 题意分析 首先我们可以得出计算公式 \[s_i=\prod_{k=1}^i(1-p_k)\] \[f_i=\sum_{k=1}^i\frac{p_k}{1-p_k}\] 那么 \[ans(i ...

  5. [USACO19FEB]Cow Dating

    Luogu5242 通过观察数据,我们可以发现,右端点的取值是单调递增的.于是,我们可以极限一波,用一个双指针法,类似于队列. 右端点的取值满足以下公式: (1-p1)(1-p2)..(1-pn) * ...

  6. [USACO19FEB]Moorio Kart(DP)

    Luogu5243 题解 即O(N^2)暴力统计出每个森林的路径,从ctgn个集合中各选出一个数,使得长度>=Y的方案数. 用背包统计.具体实现: \(dp[i+j][0]\leftarrow ...

  7. Mowing the Lawn【线性dp + 单调队列优化】

    题目链接:https://ac.nowcoder.com/acm/contest/2652/G 题目大意:与上一篇博客 烽火传递 差不多. 1.一共n头羊,若超过m头连续的羊在一起,就会集体罢工,每头 ...

  8. P5541 [USACO19FEB]Sleepy Cow Herding

    ri,被黄题虐. 思路:贪心?? 提交:2次 错因:没有特判 题解: 先排序. 最小代价:固定区间长度为\(n\),我们扫一遍数组看区间最多包含几个数,设为 \(mx\) ,答案就是\(n-mx+1\ ...

  9. [USACO19FEB]Cow Dating——找规律

    原题戳这里 题解 显然原题等价于让我们求这个式子\(\prod\limits_{i=l}^{r}(1-p_i)\sum\limits_{i=l}^{r}\frac{p_i}{1-p_i}\)的最大值是 ...

随机推荐

  1. 2016年第七届蓝桥杯javaB组 试题 答案 解析

    1.煤球数目 有一堆煤球,堆成三角棱锥形.具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), .... 如果一共有100层,共有多少个煤 ...

  2. PHP设计模式的六大设计原则

    PHP设计模式的六大设计原则 1 简介 软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化却是不可预料的.此时,我们可以通过六大设计原则良好的应对未来的变化. 2 讲解 2.1 单一职责原则 ...

  3. Windows环境下使用pip install安装lxml库

    lxml是Python语言和XML以及HTML工作的功能最丰富和最容易使用的库.lxml是为libxml2和libxslt库的一个Python化的绑定.它与众不同的地方是它兼顾了这些库的速度和功能完整 ...

  4. es6基础知识

    1.超引用:(...) 用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 function fun(...args){ console.log(args); //[1,2,3,4,5,6] ar ...

  5. C#中try catch finally 用法

    1.将预见可能引发异常的代码包含在try语句块中. 2.如果发生了异常,则转入catch的执行. catch有几种写法: catch  这将捕获任何发生的异常. catch(Exception e)  ...

  6. zookeeper安装以及遇到的一些坑

    最近项目中用到了storm,然后storm中用到了zookeeper,然后今天抽空整理一下zookeeper的安装使用,原来后期再慢慢学习. 本篇文档,操作部分是摘自其他博客,里边的问题分析是自己在实 ...

  7. 如何删除Windows10操作系统资源管理器中的下载、图片、音乐、文档、视频、桌面、3D对象这7个文件夹

    通过注册表删除,步骤如下: 1.按下win+R,输入regedit,打开注册表 2.找到位置:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Cur ...

  8. windows 2008 开机启动 Docker Toolbox 并运行容器

    新建 docker-startup.bat @echo off REM Set the name of the VM configuration where dockerd will be hoste ...

  9. SpringBoot使用qq邮箱发送邮件

    最近公司要做一个邮箱注册和重置密码的功能,因为之前就做过,但是不是Springboot项目,所以相对来说还是比较容易的,在这里记录一下. 一.引用Maven依赖 这里使用spring自带的邮件jar包 ...

  10. DEDECMS 漏洞修复方案

    目录 DEDECMS支付模块注入漏洞 漏洞文件: /include/payment/alipay.php 漏洞描述: 对输入参数$_GET['out_trade_no']未进行严格过滤 修复方案: 对 ...