博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[USACO19FEB]Mowing Mischief
阅读量:6357 次
发布时间:2019-06-23

本文共 3028 字,大约阅读时间需要 10 分钟。

题目大意:

给定平面上的一些点,求这些点的一个\(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
#define M 1000009#define N 200009using namespace std;typedef long long ll;vector
vec[N],now;vector
::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
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
>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
>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<

转载于:https://www.cnblogs.com/ZH-comld/p/10788443.html

你可能感兴趣的文章
思科表态反对网络中立
查看>>
《HTML5+CSS3网页设计入门必读》——1.5 利用多种Web浏览器执行测试
查看>>
Velocity官方指南-容器
查看>>
国家为何如此重视石墨烯?
查看>>
《Python和Pygame游戏开发指南》——1.14 配套网站上的更多信息
查看>>
利用mybatis查询两级树形菜单
查看>>
《慕客网:IOS基础入门之Foundation框架初体验》学习笔记 <一>
查看>>
Spring声明式事务管理之二:核心接口API
查看>>
LNMP环境安装(二)
查看>>
MFC对话框编程-图片控件
查看>>
nodejs启动webserver服务
查看>>
小偷被抓叫嚣:我不偷警察没饭吃
查看>>
python初学—-实现excel里面读数据进行排序
查看>>
用户体验升级后 “谁行谁上”让百度Q4财报更有底气
查看>>
直播相关学习链接
查看>>
使用RPM包工具和源码包编译安装Linux应用程序
查看>>
VoIP——开启免费通话新时代的先锋
查看>>
Linux下rsync的用法
查看>>
apache虚拟主机、日志轮询、日志统计、去版本优化
查看>>
java代码实现开启openoffice服务和关闭sffice.exe进程
查看>>