并不对劲的loj2134:uoj132:p2304:[NOI2015]小园丁与老司机
题目大意
给出平面直角坐标系中\(n\)(\(n\leq5*10^4\))个点,第\(i\)个点的坐标是\(x_i,y_i(|x_i|\leq10^9,1\leq y_i\leq10^9)\),只有朝正上方、正左方、正右方、右上方45°、左上方45°走的路,只能在给出的点处拐弯
解决两个问题:
1.从点\((0,0)\)出发,只能在没走到过的点处拐弯,求最多能走多少个给出的点并输出方案
2.从点\((0,0)\)或者任意一个给出的点出发,不能朝正左方、正右方走,而且只能走被一种第1问的最优方案包含的路,求至少要走几次才能覆盖所有被一种第1问的最优路线包含了的路
题解
先预处理每个点朝正上方、正左方、正右方、右上方45°、左上方45°走遇到的第一个点
1.
把\(y_i\)相同的点归为同一层
设\(f(i)\)表示如果从点\(i\)进入\(i\)所在的那一层,那么在\(i\)所在的层和上面的层最多能走多少给出的点
发现如果从\(i\)进入某一层,从\(j\)离开这一层,那么当\(i<j\)时该层最多走\(j\)左边所有点,当\(i>j\)时该层最多走\(j\)右边所有点,\(i=j\)时只会走到一个点
这是因为当\(i<j\)时,可以先向左走,走到\(i\)左边所有点,再向右走,走\(i,j\)之间的所有点(答案不少于\(j\)左边所有点)
而如果走到了\(j\)右边的点,就一定会走过\(j\),无法再从\(j\)离开这一层了(答案不多于\(j\)左边所有点)
\(i>j\)时同理
设\(h(x)\)表示点\(x\)左上方45°的第一个点、右上方45°的第一个点、正上方的第一个点的\(f\)的最大值
那就有\(f(i)=max(max\{h(j)+(j左边的点数)\mid i<j\},max\{h(j)+(j右边的点数)\mid i>j\},max\{h(j)+1\mid i=j\})\)
\(f(0)\)就是第一问的答案
递推\(f\)时要记方案
2.
设\(g(i)\)表示如果从点\(i\)离开\(i\)所在的那一层,那么离开时在\(i\)所在的层和下面的层最多能走多少给出的点
会发现对于一个点\(i\),它 左上方45°的第一个点 或 右上方45°的第一个点 或 正上方的第一个点 \(j\)如果满足\(g(i)+f(j)=f(0)\)那么\(i->j\)就是一条出现在第一问最优方案中的路
发现这个可以是个有上下界最小流,每条路看成下界为1,上界为\(\infty\)的边
也就是连上界为\(\infty\)的边,算出每个点的出入度后,出>入的连\(该点->超汇\)且上界为\(出-入\)的边,出<入的连\(超源->该点\)且上界为\(入-出\)的边
通过观察题意发现这题一定有解,满流就是超源到所有点的上界之和(也是所有点到超汇的上界之和),那就可以直接用(满流时的流量-重新建图后的流量)
代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k])
#define maxn 50010
#define maxm (maxn*8)
#define LL long long
#define pre(x) (!maxto[ord[x]]?tl-x+1:f[maxto[ord[x]]]+tl-x+1)
#define suf(x) (!maxto[ord[x]]?x-hd+1:f[maxto[ord[x]]]+x-hd+1)
#define now(x) (!maxto[ord[x]]?1:f[maxto[ord[x]]]+1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
return;
}
int n,xi[maxn],yi[maxn],ord[maxn],up[maxn][3],f[maxn],g[maxn],t[maxn],maxto[maxn],out[maxn],rnk[maxn],maxflow,full;
int fir[maxn],nxt[maxm],dis[maxn],v[maxm],fl[maxm],cnt,in[maxn],S,T,inf=2147483647;
bool cmpl(int x,int y){return (xi[x]+yi[x]==xi[y]+yi[y])?(yi[x]<yi[y]):(xi[x]+yi[x]<xi[y]+yi[y]);}
bool cmpr(int x,int y){return (xi[x]-yi[x]==xi[y]-yi[y])?(yi[x]<yi[y]):(xi[x]-yi[x]<xi[y]-yi[y]);}
bool cmpx(int x,int y){return (xi[x]==xi[y])?(yi[x]<yi[y]):(xi[x]<xi[y]);}
bool cmpy(int x,int y){return (yi[x]==yi[y])?(xi[x]<xi[y]):(yi[x]>yi[y]);}
void ade(int u1,int v1,int fl1)
{
v[cnt]=v1,nxt[cnt]=fir[u1],fl[cnt]=fl1,fir[u1]=cnt++;
v[cnt]=u1,nxt[cnt]=fir[v1],fl[cnt]=0,fir[v1]=cnt++;
}
int hd,tl,q[maxn];
int bfs()
{
hd=1,tl=0;
rep(i,0,T)dis[i]=inf;
dis[T]=0,q[++tl]=T;
while(hd<=tl)
{
int u=q[hd++];
view(u,k)if(fl[k^1]&&dis[v[k]]==inf)dis[v[k]]=dis[u]+1,q[++tl]=v[k];
}
return dis[S]==inf?0:1;
}
int getf(int u,int nowflow)
{
if(u==T||nowflow==0)return nowflow;
int tmp,sum=0;
view(u,k)
{
if(!nowflow)break;
if(dis[v[k]]==dis[u]-1&&fl[k]&&(tmp=getf(v[k],min(nowflow,fl[k]))))fl[k]-=tmp,fl[k^1]+=tmp,nowflow-=tmp,sum+=tmp;
}
return sum;
}
int main()
{
memset(fir,-1,sizeof(fir));
n=read();
rep(i,1,n)xi[i]=read(),yi[i]=read(),ord[i]=i;
sort(ord,ord+n+1,cmpl);
rep(i,0,n-1){if(xi[ord[i+1]]+yi[ord[i+1]]==xi[ord[i]]+yi[ord[i]])up[ord[i]][0]=ord[i+1];}
sort(ord,ord+n+1,cmpr);
rep(i,0,n-1){if(xi[ord[i+1]]-yi[ord[i+1]]==xi[ord[i]]-yi[ord[i]])up[ord[i]][1]=ord[i+1];}
sort(ord,ord+n+1,cmpx);
rep(i,0,n-1){if(xi[ord[i+1]]==xi[ord[i]])up[ord[i]][2]=ord[i+1];}
sort(ord,ord+n+1,cmpy);int pos;
rep(i,0,n)
{
hd=i,tl=i;
while(tl+1<=n&&yi[ord[tl+1]]==yi[ord[hd]])tl++;
rep(j,hd,tl)rep(k,0,2){if(up[ord[j]][k]&&(!maxto[ord[j]]||f[up[ord[j]][k]]>f[maxto[ord[j]]]))maxto[ord[j]]=up[ord[j]][k];}
pos=-1;
rep(j,hd,tl)f[ord[j]]=now(j),out[ord[j]]=(!maxto[ord[j]])?-1:ord[j],rnk[ord[j]]=j;
rep(j,hd,tl)
{
if(pos!=-1&&pre(pos)>f[ord[j]])f[ord[j]]=pre(pos),out[ord[j]]=ord[pos];
if(pos==-1||pre(j)>pre(pos))pos=j;
}pos=-1;
dwn(j,tl,hd)
{
if(pos!=-1&&suf(pos)>f[ord[j]])f[ord[j]]=suf(pos),out[ord[j]]=ord[pos];
if(pos==-1||suf(j)>suf(pos))pos=j;
}
i=tl;
}
//rep(i,0,n)cout<<"maxto:"<<maxto[i]<<" out:"<<out[i]<<endl;
write(f[0]-1),putchar('\n');
pos=maxto[0];
if(maxto[0])
{
do
{
if(rnk[out[pos]]<rnk[pos])
{
for(int i=rnk[pos];yi[ord[i]]==yi[pos];i++)write(ord[i]),putchar(' ');
for(int i=rnk[pos]-1;yi[ord[i]]==yi[pos]&&i>=rnk[out[pos]];i--)write(ord[i]),putchar(' ');
}
else if(rnk[out[pos]]>rnk[pos])
{
for(int i=rnk[pos];yi[ord[i]]==yi[pos];i--)write(ord[i]),putchar(' ');
for(int i=rnk[pos]+1;yi[ord[i]]==yi[pos]&&i<=rnk[out[pos]];i++)write(ord[i]),putchar(' ');
}
else write(pos),putchar(' ');
pos=out[pos];
if(out[pos]==-1)break;
pos=maxto[pos];
}while(pos);
putchar('\n');
}
rep(i,0,n)t[i]=g[i]=-n*4;g[0]=1;
dwn(i,n,0)
{
hd=i,tl=i;
while(hd-1>=0&&yi[ord[hd-1]]==yi[ord[tl]])hd--;
pos=-1;
rep(j,hd,tl)if(t[ord[j]]>0)g[ord[j]]=t[ord[j]]+1;
rep(j,hd,tl)
{
if(pos!=-1)g[ord[j]]=max(g[ord[j]],t[ord[pos]]+j-hd+1);
if(t[ord[j]]>0&&(pos==-1||t[ord[pos]]<t[ord[j]]))pos=j;
}pos=-1;
dwn(j,tl,hd)
{
if(pos!=-1)g[ord[j]]=max(g[ord[j]],t[ord[pos]]+tl-j+1);
if(t[ord[j]]>0&&(pos==-1||t[ord[pos]]<t[ord[j]]))pos=j;
}
rep(j,hd,tl)if(g[ord[j]]>0){rep(k,0,2)if(up[ord[j]][k])t[up[ord[j]][k]]=max(t[up[ord[j]][k]],g[ord[j]]);}
i=hd;
}
S=n+1,T=n+2;
rep(i,0,n)rep(k,0,2)if(up[i][k]&&g[i]>0&&g[i]+f[up[i][k]]==f[0])in[i]--,in[up[i][k]]++,ade(i,up[i][k],inf);
rep(i,0,n)
{
if(in[i]<0)ade(i,T,-in[i]);
if(in[i]>0)ade(S,i,in[i]),full+=in[i];
}
while(bfs())maxflow+=getf(S,inf);write(full-maxflow);
return 0;
}
/*
6
-1 1
1 1
-2 2
0 8
0 9
0 10
*/
/*
4
0 1
-2 1
2 1
3 2
*/
并不对劲的loj2134:uoj132:p2304:[NOI2015]小园丁与老司机的更多相关文章
- luogu P2304 [NOI2015]小园丁与老司机 dp 上下界网络流
LINK:小园丁与老司机 苦心人 天不负 卧薪尝胆 三千越甲可吞吴 AC的刹那 真的是泪目啊 很久以前就写了 当时记得特别清楚 写到肚子疼.. 调到胳膊疼.. ex到根不不想看的程度. 当时wa了 一 ...
- uoj132/BZOJ4200/洛谷P2304 [Noi2015]小园丁与老司机 【dp + 带上下界网络流】
题目链接 uoj132 题解 真是一道大码题,,,肝了一个上午 老司机的部分是一个\(dp\),观察点是按\(y\)分层的,而且按每层点的上限来看可以使用\(O(nd)\)的\(dp\),其中\(d\ ...
- BZOJ4200 & 洛谷2304 & UOJ132:[NOI2015]小园丁与老司机——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...
- [BZOJ4200][Noi2015]小园丁与老司机
4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 106 Solved ...
- [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机
[UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机 试题描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 \(n\) 棵许愿 ...
- 【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流
[BZOJ2839][Noi2015]小园丁与老司机 Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2, ...
- [BZOJ]4200: [Noi2015]小园丁与老司机
Time Limit: 20 Sec Memory Limit: 512 MBSec Special Judge Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维 ...
- [Noi2015]小园丁和老司机
来自FallDream的博客,未经允许,请勿转载,谢谢. 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有n棵许愿树,编号1,2,3,…,n,每棵树可以看作平面上的一个点,其中 ...
- 【bzoj4200】[Noi2015]小园丁与老司机 STL-map+dp+有上下界最小流
题目描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤ ...
随机推荐
- HDU 4436 str2int
str2int Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ID: 4 ...
- python3--shelve 模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 import shelve d = shelve.open('shelve_t ...
- XV6上下文切换
上下文切换分为两种情况 用户程序陷入到内核,再从内核返回 两个应用程序之间的上下文切换 用户程序陷入到内核 用户程序陷入到内核通过中断INT指令,在xv6中系统调用的号为64 操作系统在初始化的时候会 ...
- ubuntu 18.04取消自动锁屏以及设置键盘快捷锁屏
1:操作设置取消自动锁屏: setting-->power--->never 2: 设置自动锁屏快捷键: 快捷键设置一般在setting-->devices--->keybo ...
- 假面舞会(codevs 1800)
题目描述 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会. 今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择 一个自己喜欢的面具.每个面具都有一 ...
- BZOJ1733: [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机
n<=200个点m<=40000条边无向图,求 t次走不经过同条边的路径从1到n的经过的边的最大值 的最小值. 最大值最小--二分,t次不重边路径--边权1的最大流. #inclu ...
- js1:对象的学习,构造函数,继承构造函数【使用教材:JavaScript深度剖析第2版】
原文发布时间为:2008-11-08 -- 来源于本人的百度文章 [由搬家工具导入] <html> <head> <title>js</title> & ...
- hdu 4046 Panda [线段树]
Panda Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- D. Little Artem and Dance---cf669D
http://codeforces.com/problemset/problem/669/D 题目大意: 有n对人 男生和女生 开始时 每个人的标号是(1,2,3,...n) 女生们围成一个圈 男 ...
- [洛谷U22156]未曾届到游览(矩阵树定理)
题目背景 又到了某任*堂开关中学一年一度的自主招生考试的时间了,在考试完后许多家长决定带着自己的孩子参观一下这所距千年名校还有890周年的百年学校: 题目描述 这所学校的布局非常奇怪,是一个由N 个点 ...