jzoj3578 【CEOI2013】Adriatic 巧妙dp
来源:互联网 发布:淘宝店怎么找上家 编辑:程序博客网 时间:2024/05/19 13:55
题意
平面上若干个点,每个点(x,y)可以到达满足
3<=N<=250 000,0<坐标<=2500
分析
考虑到一个点将会把图分成四份区域。其中两个区域(左下,右上)是可以直接到达x的,那这个贡献就好算. 我们要算的只是另外两个区域.
两个区域差不多,只讲一个好了(左上)
画个图发现,左上的点必然会先跑进左下,右上,然后才能进点x.
于是我们设f[i][j]表示,一个以(i,j)为右下角的左上区域,他里面的所有点跑进左下,右上的最小代价。
如何更新?
找到两个蓝色区域的严格更新线,也就是说,在图中两条虚线的左上角那个框框(x0,y0)里的所有点,都不能直接走到蓝色区域里.
然后,f[x][y]=f[x0][y0]+sum(x,y),sum(x,y)表示左上角白色区域iii里的点数.
因为虚线划分出来的白色区域需要再走一步才能走到黄色区域里(保证有解),所以这一区域里的点要算走出来的方案f[x0][y0]走到黄色区域,然后再走一步走到蓝色区域里.
不难发现用严格更新线构成的矩阵更新是最优的 (黄色区域里的一步肯定最优,小白色区域必须先走到黄色区域,再走出来,那就满足最优子结构)
左上右下都做一次,答案很好算
#include <cstdio>#include <iostream>#include <cstring>#define can(x,y) ((zx[x]<zx[y] && zy[x]<zy[y]) || (zx[x]>zx[y] && zy[x]>zy[y]))using namespace std;const int N = 250010,M = 2510;int zx[N],zy[N];int n,lx,ly;int Q[N],head,tail,dis[N],bz[N];int minh[M],minl[M],maxh[M],maxl[M];int f[M][M],f2[M][M],cnt[M][M];int sum(int lx,int ly,int rx,int ry) { return cnt[rx][ly] - cnt[rx][ry-1] - cnt[lx-1][ly] + cnt[lx-1][ry-1];}int main() { freopen("3578.in","r",stdin);freopen("3578.out","w",stdout); cin>>n; memset(minh,127,sizeof minh); memset(minl,127,sizeof minl); for (int i=1; i<=n; i++) { scanf("%d %d",&zx[i],&zy[i]); cnt[zx[i]][zy[i]]++; lx=max(lx,zx[i]),ly=max(ly,zy[i]); minh[zx[i]]=min(minh[zx[i]],zy[i]); maxh[zx[i]]=max(maxh[zx[i]],zy[i]); minl[zy[i]]=min(minl[zy[i]],zx[i]); maxl[zy[i]]=max(maxl[zy[i]],zx[i]); } for (int i=1; i<=lx; i++) for (int j=1; j<=ly; j++) cnt[i][j]+=cnt[i-1][j] + cnt[i][j-1] - cnt[i-1][j-1]; for (int i=lx; i; i--) maxh[i]=max(maxh[i],maxh[i+1]); for (int i=ly; i; i--) maxl[i]=max(maxl[i],maxl[i+1]); minl[0]=lx+1, minh[0]=ly+1; for (int i=1; i<=lx; i++) minh[i]=min(minh[i],minh[i-1]); for (int i=1; i<=ly; i++) minl[i]=min(minl[i],minl[i-1]); for (int i=ly; i; i--) for (int j=1; j<=lx; j++) { int topy=max(i,maxh[j+1]),topx=min(j,minl[i-1]); f[j][i]=f[topx][topy] + sum(1,ly,j,i); } for (int i=1; i<=ly; i++) for (int j=lx; j; j--) { int topy=min(i,minh[j-1]),topx=max(j,maxl[i+1]); f2[j][i]=f2[topx][topy] + sum(j,i,lx,1); } for (int i=1; i<=n; i++) { printf("%d\n",f[zx[i]][zy[i]] + f2[zx[i]][zy[i]] + n - 3); }}
阅读全文
0 0
- jzoj3578 【CEOI2013】Adriatic 巧妙dp
- [JZOJ3578] Adriatic
- 【CEOI2013】Adriatic
- [jzoj]3578. 【CEOI2013】Adriatic(记忆化/DP)
- bzoj 3341: [Ceoi2013]adriatic
- 3341: [Ceoi2013]adriatic
- bzoj 3341: [Ceoi2013]adriatic 动态规划
- bzoj3341: [Ceoi2013]adriatic 记忆化搜索
- AHOI2009中国象棋--巧妙dp
- SPOJ 12943. Counting, dp ,巧妙
- CF822E,巧妙的字符串DP
- HDOJ - 3578 DP...巧妙构造DP状态
- CEOI2013部分题解
- poj3557 一个很巧妙的概率dp
- Hotal (巧妙地dp设计)
- 【巧妙消维DP】【HDU2059】龟兔赛跑
- Codeforces Beta Round #51---D. Beautiful numbers(数位dp, 巧妙)
- CodeForces 543d Road Improvement(巧妙地树形dp)
- Recyclerview的点击事件
- 关于拉电流与灌电流
- Python filter()函数
- git cherry pick代码
- Spark常用算子详解汇总 : 实战案例、Java版本、Scala版本
- jzoj3578 【CEOI2013】Adriatic 巧妙dp
- 国内优秀的人工智能公司
- 594. Longest Harmonious Subsequence
- Oracle数据库 Insert 多行Values
- 框架和设计模式的区别
- error C2440: “类型转换”: 无法从“LPVOID”转换为“double
- Python网络数据采集
- Linux SoftEther VPN Client 使用说明
- Jmeter性能测试基础实战