题目大意

给出平面直角坐标系中\(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\)的边,算出每个点的出入度后,出>入的连\(该点->超汇\)且上界为\(出-入\)的边,出<入的连\(超源->该点\)且上界为\(入-出\)的边

通过观察题意发现这题一定有解,满流就是超源到所有点的上界之和(也是所有点到超汇的上界之和),那就可以直接用(满流时的流量-重新建图后的流量)

代码
  1. #include<algorithm>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<ctime>
  7. #include<iomanip>
  8. #include<iostream>
  9. #include<map>
  10. #include<queue>
  11. #include<set>
  12. #include<stack>
  13. #include<vector>
  14. #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
  15. #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
  16. #define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k])
  17. #define maxn 50010
  18. #define maxm (maxn*8)
  19. #define LL long long
  20. #define pre(x) (!maxto[ord[x]]?tl-x+1:f[maxto[ord[x]]]+tl-x+1)
  21. #define suf(x) (!maxto[ord[x]]?x-hd+1:f[maxto[ord[x]]]+x-hd+1)
  22. #define now(x) (!maxto[ord[x]]?1:f[maxto[ord[x]]]+1)
  23. using namespace std;
  24. int read()
  25. {
  26. int x=0,f=1;char ch=getchar();
  27. while(!isdigit(ch)&&ch!='-')ch=getchar();
  28. if(ch=='-')f=-1,ch=getchar();
  29. while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
  30. return x*f;
  31. }
  32. void write(int x)
  33. {
  34. if(x==0){putchar('0');return;}
  35. int f=0;char ch[20];
  36. if(x<0)putchar('-'),x=-x;
  37. while(x)ch[++f]=x%10+'0',x/=10;
  38. while(f)putchar(ch[f--]);
  39. return;
  40. }
  41. 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;
  42. int fir[maxn],nxt[maxm],dis[maxn],v[maxm],fl[maxm],cnt,in[maxn],S,T,inf=2147483647;
  43. 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]);}
  44. 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]);}
  45. bool cmpx(int x,int y){return (xi[x]==xi[y])?(yi[x]<yi[y]):(xi[x]<xi[y]);}
  46. bool cmpy(int x,int y){return (yi[x]==yi[y])?(xi[x]<xi[y]):(yi[x]>yi[y]);}
  47. void ade(int u1,int v1,int fl1)
  48. {
  49. v[cnt]=v1,nxt[cnt]=fir[u1],fl[cnt]=fl1,fir[u1]=cnt++;
  50. v[cnt]=u1,nxt[cnt]=fir[v1],fl[cnt]=0,fir[v1]=cnt++;
  51. }
  52. int hd,tl,q[maxn];
  53. int bfs()
  54. {
  55. hd=1,tl=0;
  56. rep(i,0,T)dis[i]=inf;
  57. dis[T]=0,q[++tl]=T;
  58. while(hd<=tl)
  59. {
  60. int u=q[hd++];
  61. view(u,k)if(fl[k^1]&&dis[v[k]]==inf)dis[v[k]]=dis[u]+1,q[++tl]=v[k];
  62. }
  63. return dis[S]==inf?0:1;
  64. }
  65. int getf(int u,int nowflow)
  66. {
  67. if(u==T||nowflow==0)return nowflow;
  68. int tmp,sum=0;
  69. view(u,k)
  70. {
  71. if(!nowflow)break;
  72. 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;
  73. }
  74. return sum;
  75. }
  76. int main()
  77. {
  78. memset(fir,-1,sizeof(fir));
  79. n=read();
  80. rep(i,1,n)xi[i]=read(),yi[i]=read(),ord[i]=i;
  81. sort(ord,ord+n+1,cmpl);
  82. 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];}
  83. sort(ord,ord+n+1,cmpr);
  84. 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];}
  85. sort(ord,ord+n+1,cmpx);
  86. rep(i,0,n-1){if(xi[ord[i+1]]==xi[ord[i]])up[ord[i]][2]=ord[i+1];}
  87. sort(ord,ord+n+1,cmpy);int pos;
  88. rep(i,0,n)
  89. {
  90. hd=i,tl=i;
  91. while(tl+1<=n&&yi[ord[tl+1]]==yi[ord[hd]])tl++;
  92. 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];}
  93. pos=-1;
  94. rep(j,hd,tl)f[ord[j]]=now(j),out[ord[j]]=(!maxto[ord[j]])?-1:ord[j],rnk[ord[j]]=j;
  95. rep(j,hd,tl)
  96. {
  97. if(pos!=-1&&pre(pos)>f[ord[j]])f[ord[j]]=pre(pos),out[ord[j]]=ord[pos];
  98. if(pos==-1||pre(j)>pre(pos))pos=j;
  99. }pos=-1;
  100. dwn(j,tl,hd)
  101. {
  102. if(pos!=-1&&suf(pos)>f[ord[j]])f[ord[j]]=suf(pos),out[ord[j]]=ord[pos];
  103. if(pos==-1||suf(j)>suf(pos))pos=j;
  104. }
  105. i=tl;
  106. }
  107. //rep(i,0,n)cout<<"maxto:"<<maxto[i]<<" out:"<<out[i]<<endl;
  108. write(f[0]-1),putchar('\n');
  109. pos=maxto[0];
  110. if(maxto[0])
  111. {
  112. do
  113. {
  114. if(rnk[out[pos]]<rnk[pos])
  115. {
  116. for(int i=rnk[pos];yi[ord[i]]==yi[pos];i++)write(ord[i]),putchar(' ');
  117. for(int i=rnk[pos]-1;yi[ord[i]]==yi[pos]&&i>=rnk[out[pos]];i--)write(ord[i]),putchar(' ');
  118. }
  119. else if(rnk[out[pos]]>rnk[pos])
  120. {
  121. for(int i=rnk[pos];yi[ord[i]]==yi[pos];i--)write(ord[i]),putchar(' ');
  122. for(int i=rnk[pos]+1;yi[ord[i]]==yi[pos]&&i<=rnk[out[pos]];i++)write(ord[i]),putchar(' ');
  123. }
  124. else write(pos),putchar(' ');
  125. pos=out[pos];
  126. if(out[pos]==-1)break;
  127. pos=maxto[pos];
  128. }while(pos);
  129. putchar('\n');
  130. }
  131. rep(i,0,n)t[i]=g[i]=-n*4;g[0]=1;
  132. dwn(i,n,0)
  133. {
  134. hd=i,tl=i;
  135. while(hd-1>=0&&yi[ord[hd-1]]==yi[ord[tl]])hd--;
  136. pos=-1;
  137. rep(j,hd,tl)if(t[ord[j]]>0)g[ord[j]]=t[ord[j]]+1;
  138. rep(j,hd,tl)
  139. {
  140. if(pos!=-1)g[ord[j]]=max(g[ord[j]],t[ord[pos]]+j-hd+1);
  141. if(t[ord[j]]>0&&(pos==-1||t[ord[pos]]<t[ord[j]]))pos=j;
  142. }pos=-1;
  143. dwn(j,tl,hd)
  144. {
  145. if(pos!=-1)g[ord[j]]=max(g[ord[j]],t[ord[pos]]+tl-j+1);
  146. if(t[ord[j]]>0&&(pos==-1||t[ord[pos]]<t[ord[j]]))pos=j;
  147. }
  148. 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]]);}
  149. i=hd;
  150. }
  151. S=n+1,T=n+2;
  152. 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);
  153. rep(i,0,n)
  154. {
  155. if(in[i]<0)ade(i,T,-in[i]);
  156. if(in[i]>0)ade(S,i,in[i]),full+=in[i];
  157. }
  158. while(bfs())maxflow+=getf(S,inf);write(full-maxflow);
  159. return 0;
  160. }
  161. /*
  162. 6
  163. -1 1
  164. 1 1
  165. -2 2
  166. 0 8
  167. 0 9
  168. 0 10
  169. */
  170. /*
  171. 4
  172. 0 1
  173. -2 1
  174. 2 1
  175. 3 2
  176. */

并不对劲的loj2134:uoj132:p2304:[NOI2015]小园丁与老司机的更多相关文章

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

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

  2. uoj132/BZOJ4200/洛谷P2304 [Noi2015]小园丁与老司机 【dp + 带上下界网络流】

    题目链接 uoj132 题解 真是一道大码题,,,肝了一个上午 老司机的部分是一个\(dp\),观察点是按\(y\)分层的,而且按每层点的上限来看可以使用\(O(nd)\)的\(dp\),其中\(d\ ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. 【bzoj4200】[Noi2015]小园丁与老司机 STL-map+dp+有上下界最小流

    题目描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤ ...

随机推荐

  1. 【板+背包】多重背包 HDU Coins

    http://acm.hdu.edu.cn/showproblem.php?pid=2844 [题意] 给定n种价值为Ci,个数为Wi的硬币,问在1~V中的这些数中哪些数能由这些硬币组成? [思路] ...

  2. java web 项目常用框架

    java框架实在是太多了,网上一搜索一大箩筐,根本就了解不到什么. 我还是以我的经验来说一下j2ee的框架. 1.首先力推struts2框架,这是最经典的框架(可以说没有“之一”).可以帮你快速搭建出 ...

  3. 2016 Multi-University Training Contest 1 solutions BY HIT

    首先向大家表示抱歉,因为这套题是去年出的,中间间隔时间太长,今年又临时准备仓促, 所以部分题目出现了一些问题,非常抱歉. Abandoned country 首先注意到任意两条边的边权是不一样的,由此 ...

  4. 栈 练习 Codevs 3137 3138 3139

    3137 栈练习1 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 给定一个栈(初始为空,元素类型为整数,且小于等于100),只 ...

  5. Codeforces Round #298 (Div. 2) D. Handshakes [贪心]

    传送门 D. Handshakes time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  6. AndroidUI的基本结构

    AndroidUI的基本结构 创建时间: 2013-9-13 11:05 更新时间: 2013-9-13 11:05

  7. ubuntu-12.04下安装postgresql

    2013-10-01 20:42:57|    moniter参考资料:Ubuntu 12.04下PostgreSQL-9.1安装与配置详解(在线安装)一.安装postgresqlbamboo@bam ...

  8. poj——3177Redundant Paths

    poj——3177Redundant Paths      洛谷—— P2860 [USACO06JAN]冗余路径Redundant Paths Time Limit: 1000MS   Memory ...

  9. ultraiso:usb-hdd+ v2

    http://cn.ezbsystems.com/ultraiso/download.htm 普通隐藏:建立一个LBA前置的PBR包含表头的活动分区.高端隐藏:建立一个LBA后置的PBR包含表头的活动 ...

  10. 搭建网络svn实战

    工作中的问题(7) 转自:http://blog.csdn.net/xiaoting451292510/article/details/8562570 经常性我们和朋友写一些程序,大家在不同的城市确有 ...