洛谷上有个点死活卡不过去,不知道是哪里写丑了orz

参考:https://www.cnblogs.com/ditoly/p/BZOJ4200.html

从上往下dp,设f为不向左右走直接上去的值,g为先向左右走一步再上去,至于找每个方向上的点,分别按x,y,x+y,x-y排序然后二分即可

然后建出左上右上的图,跑有上下界最小流即可

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int N=50005;
int n,rl[N],t1[N],t2[N],t3[N],l[N],r[N],f[N],ff[N],lf[N],rf[N],a[N],an,d[N],u[N],c[N],s,t,ans,h[N],cnt=1,le[N];
vector<int>v,b[N];
struct qwe
{
int ne,to,va;
}e[N*10];
struct dian
{
int x,y,id;
}p[N];
bool cmp1(const dian&a,const dian&b)
{
return a.x+a.y==b.x+b.y?a.y<b.y:a.x+a.y<b.x+b.y;
}
bool cmp2(const dian&a,const dian&b)
{
return a.x-a.y==b.x-b.y?a.y<b.y:a.x-a.y<b.x-b.y;
}
bool cmp3(const dian&a,const dian&b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;
}
bool cmp4(const dian&a,const dian&b)
{
return a.y==b.y?a.x<b.x:a.y<b.y;
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v,int w)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
e[cnt].va=w;
h[u]=cnt;
}
void ins(int u,int v,int w)
{
add(u,v,w);
add(v,u,0);
}
void wk(int u,int v,int l,int r)
{
c[u]-=l,c[v]+=l;
ins(u,v,r-l);
}
bool bfs()
{
memset(le,0,sizeof(le));
queue<int>q;
le[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(e[i].va>0&&!le[e[i].to])
{
le[e[i].to]=le[u]+1;
q.push(e[i].to);
}
}
return le[t];
}
int dfs(int u,int f)
{
if(u==t||!f)
return f;
int us=0;
for(int i=h[u];i&&us<f;i=e[i].ne)
if(e[i].va>0&&le[e[i].to]==le[u]+1)
{
int t=dfs(e[i].to,min(e[i].va,f-us));
e[i].va-=t;
e[i^1].va+=t;
us+=t;
}
if(!us)
le[u]=0;
return us;
}
int dinic()
{
int r=0;
while(bfs())
r+=dfs(s,1e9);
return r;
}
void jia(int x,int y)
{
if(ff[y]+1>f[x])
f[x]=ff[y]+1,b[x].clear();
if(ff[y]+1==f[x])
b[x].push_back(y);
}
void prin(int x)
{
a[++an]=x;
int u=1;
if(f[x]==ff[x])
{
u=0;
if(p[x].id)
prin(b[x][0]);
}
for(int i=l[x];u&&i<x;i++)
if(f[i]+x-l[x]==ff[x])
{
u=0;
for(int j=x;--j>i;)
a[++an]=j;
for(int j=l[x];j<=i;j++)
a[++an]=j;
if(p[i].id)
prin(b[i][0]);
}
for(int i=r[x];u&&i>x;i--)
if(f[i]+r[x]-x==ff[x])
{
u=0;
for(int j=x;++j<i;)
a[++an]=j;
for(int j=r[x];j>=i;j--)
a[++an]=j;
if(p[i].id)
prin(b[i][0]);
}
}
void dfs(int x)
{
if(d[x])
return;
d[x]=1;
if(f[x]==ff[x]&&!u[x])
{
u[x]=1;
for(int i=0;i<b[x].size();i++)
wk(b[x][i],x,1,1e9),dfs(b[x][i]);
}
for(int i=l[x];i<x;i++)
if(f[i]+x-l[x]==ff[x]&&!u[i])
{
u[i]=1;
for(int j=0;j<b[i].size();j++)
wk(b[i][j],i,1,1e9),dfs(b[i][j]);
}
for(int i=r[x];i>x;i--)
if(f[i]+r[x]-x==ff[x]&&!u[i])
{
u[i]=1;
for(int j=0;j<b[i].size();j++)
wk(b[i][j],i,1,1e9),dfs(b[i][j]);
}
}
int main()
{
n=read();
s=n+3,t=n+4;
for(int i=1;i<=n;++i)
p[i].x=read(),p[i].y=read(),p[i].id=i;
sort(p,p+n+1,cmp1);
for(int i=0;i<n;i++)
if(p[i].x+p[i].y==p[i+1].x+p[i+1].y)
t1[p[i].id]=p[i+1].id;
sort(p,p+n+1,cmp2);
for(int i=0;i<n;i++)
if(p[i].x-p[i].y==p[i+1].x-p[i+1].y)
t2[p[i].id]=p[i+1].id;
sort(p,p+n+1,cmp3);
for(int i=0;i<n;i++)
if(p[i].x==p[i+1].x)
t3[p[i].id]=p[i+1].id;
sort(p,p+n+1,cmp4);
for(int i=0;i<=n;i++)
rl[p[i].id]=i;
memset(f,200,sizeof(f));
f[rl[0]]=0;
for(int i=0;i<=n;i=r[i]+1)
{
for(l[i]=r[i]=i;r[i]<n&&p[r[i]+1].y==p[r[i]].y;++r[i]);
for(int j=l[i];++j<=r[i];)
l[j]=l[i],r[j]=r[i];
lf[l[i]]=-1e9;
for(int j=l[i];++j<=r[i];)
lf[j]=max(lf[j-1],f[j-1]);
rf[r[i]]=-1e9;
for(int j=r[i];--j>=l[i];)
rf[j]=max(rf[j+1],f[j+1]);
for(int j=l[i];j<=r[i];j++)
{
ff[j]=max(f[j],max(lf[j]+j-l[i],rf[j]+r[i]-j));
if(t1[p[j].id])
jia(rl[t1[p[j].id]],j);
if(t2[p[j].id])
jia(rl[t2[p[j].id]],j);
if(t3[p[j].id])
jia(rl[t3[p[j].id]],j);
if(ff[j]>ans)
ans=ff[j],v.clear();
if(ff[j]==ans)
v.push_back(j);
}
}
printf("%d\n",ans);
prin(v[0]);
for(int i=an-1;i>=1;i--)
printf("%d ",p[a[i]].id);
puts("");
for(int i=0;i<v.size();i++)
dfs(v[i]);
for(int i=0;i<=n;i++)
wk(n+1,i,0,1e9),wk(i,n+2,0,1e9);
for(int i=0;i<=n;i++)
{
if(c[i]>0)
ins(s,i,c[i]);
else
ins(i,t,-c[i]);
}
int la0=h[n+1],la1=h[n+2];
ins(n+2,n+1,1e9);
dinic();
int ans=e[cnt].va;//cerr<<ans<<endl;
h[n+1]=la0,h[n+2]=la1;
s=n+2,t=n+1;
printf("%d\n",ans-dinic());
return 0;
}

bzoj 4200: [Noi2015]小园丁与老司机【dp+有上下界最小流】的更多相关文章

  1. [BZOJ]4200: [Noi2015]小园丁与老司机

    Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special Judge Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维 ...

  2. BZOJ4200 NOI2015小园丁与老司机(动态规划+上下界网络流)

    一看上去就是一个二合一的题.那么先解决第一部分求最优路线(及所有可能在最优路线上的线段). 由于不能往下走,可以以y坐标作为阶段.对于y坐标不同的点,我们将可以直接到达的两点连边,显然这样的边的个数是 ...

  3. 【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流

    [BZOJ2839][Noi2015]小园丁与老司机 Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2, ...

  4. luogu P2304 [NOI2015]小园丁与老司机 dp 上下界网络流

    LINK:小园丁与老司机 苦心人 天不负 卧薪尝胆 三千越甲可吞吴 AC的刹那 真的是泪目啊 很久以前就写了 当时记得特别清楚 写到肚子疼.. 调到胳膊疼.. ex到根不不想看的程度. 当时wa了 一 ...

  5. [NOI2015]小园丁与老司机(DP+上下界最小流)

    由于每行点的个数不超过1000,所以行内DP可以使用$O(n^2)$算法. 先找到每个点所能直接到达的所有点(x,y,x+y或x-y相同),用排序实现. 第一问:以行为阶段,对于每行,暴力枚举最有路径 ...

  6. [BZOJ4200][Noi2015]小园丁与老司机

    4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 106  Solved ...

  7. [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机

    [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机 试题描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 \(n\) 棵许愿 ...

  8. [Noi2015]小园丁和老司机

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有n棵许愿树,编号1,2,3,…,n,每棵树可以看作平面上的一个点,其中 ...

  9. BZOJ4200 & 洛谷2304 & UOJ132:[NOI2015]小园丁与老司机——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...

随机推荐

  1. ArrayList概述

    一. ArrayList概述: ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境 ...

  2. mysql user password plugin

    caching_sha2_passwordcaching_sha2_passwordcaching_sha2_passwordcaching_sha2_passwordcaching_sha2_pas ...

  3. static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符

    总结: 1.无论一个类实例化多少对象,它的静态变量只有一份拷贝: 静态域属于类,而非由类构造的实例化的对象,所有类的实例对象共享静态域. class Employee { private static ...

  4. 虚拟化(四):vsphere高可用功能前提-共享存储搭建(使用微软提供的iscsi software target,也可以使用免费开源的openfiler)

    虚拟化(一):虚拟化及vmware产品介绍 虚拟化(二):虚拟化及vmware workstation产品使用 虚拟化(三):vsphere套件的安装注意及使用 虚拟化(四):vsphere高可用功能 ...

  5. hdu 3415 单调队列

    Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  6. Safair 浏览器cllick事件不生效或者需要双击才生效

    针对Safair 浏览器cllick事件不生效或者需要双击才生效的解决方案. 方法一:给元素加上cursor: pointer样式.(不生效) 方法二:ios事件机制不一样,将click事件改为mou ...

  7. 转载-jmeter进阶功能

    在这此对新版本jmeter的学习+温习的过程,发现了一些以前不知道的功能,所以,整理出来与大分享.本文内容如下. 如何使用英文界面的jmeter 如何使用镜像服务器 Jmeter分布式测试 启动Deb ...

  8. HDU 1829/POJ 2492 A Bug's Life

    A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. window上安装rabbitMQ

    win7下安装RabbitMQ http://my.oschina.net/ydsakyclguozi/blog/528835?fromerr=q7m1OxxF 前辈总结的特别详细.

  10. MySQL学习笔记(六)—— MySQL自连接

    有的时候我们需要对同一表中的数据进行多次检索,这个时候我们可以使用之前学习过的子查询,先查询出需要的数据,再进行一次检索. 例如:一张products表,有产品id,供应商id(vend_id),产品 ...