题目大意

  有一个 \(2^n\times 2^n\) 的网格,左下角坐标为 \((0,0)\),右上角坐标为 \((2^n,2^n)\)。

  定义格点 \((x,y)\) 为坐标系中坐标为 \((x,y)\) 的整点。

  定义格子 \((x,y)\) 为左下角格点为 \((x,y)\),右上角格点为 \((x+1,y+1)\) 的格子。

  你要给每个格子标号:若一个格子的坐标为 \((x,y)\),其中 \(x=(x_0x_1\ldots x_{n-1}),y=(y_0y_1\ldots y_{n-1})\),则这个格子的编号为 \((x_0y_0x_1y_1\ldots x_{n-1}y_{n-1})\)。

  网格上有一个 \(m\) 个点的简单多边形。这个多边形的所有顶点都是整点,所有边都与坐标轴平行。

  记 \(C\) 为多边形内所有格子的编号组成的集合。

  你每次操作可以选择两个数 \([l,r]\),删去 \(C\) 中 \([l,r]\) 之间的所有数,代价为 \(r-l+1\)。

  每次给你一个 \(k\),问你在操作不超过 \(k\) 次的情况下删去 \(C\) 中的所有数,最少总代价是多少。

  \(n\leq 30,m\leq 200,q\leq {10}^6\)

题解

  先把 \(C\) 中所有连续段找出来。记个数为 \(cnt\),\(\lvert C\rvert =tot\)。

  那么当 \(k\geq cnt\) 时答案为 \(tot\)。

  当 \(k\) 变小时,每次要选两个相邻的连续段,把这两个连续段中间的空隙填上。

  显然每次选的一定是最小的空隙。

  那么我们只用处理出每种长度的空隙的个数就好了。

  先讲一下官方题解的做法:

  对于一个矩形,我们求出这个矩形内所有空隙的长度和多边形与这个矩形的交中编号最小最大的点。

  每次对于一个矩形 \((xl,xr,yl,yr)\),如果这个矩形是正方形,就把这个矩形沿着 \(x=\frac{(xl+xr)}{2}\) 切开,否则就沿着 \(y=\frac{yl+yr}{2}\) 切开。当然你把每个正方形都切成四块也是可以的。

  这样每个矩形内的格子的编号都是连续的。

  如果切开来的两个矩形形状相同,就只递归一边,否则就两边都递归。

  每次会产生多个长度为 \(s2.min-s1.max-1\) 的空隙。

  题解说这样做的时间复杂度是 \(O(nm^3)\) 的。

  有一个更好的做法:

  首先,矩形和空隙长度都只有 \(O(nm)\) 种。

  搜索树有 \(O(n)\) 层。对于搜索的树每一层,把多边形放到这一层所有矩形组成的网格中。

  把多边形顶点所在的矩形染成红色,把与红色矩形相邻的矩形染成蓝色,剩下的矩形是白色的。

  对于一个白色的矩形,如果这个矩形没有被多边形完全覆盖,也没有和多边形相离,那么这个矩形一定和某一个蓝色矩形是相同的。

  这样每层只有 \(O(m)\) 个矩形,总共有 \(O(nm)\) 个矩形。所以空隙长度也只有 \(O(nm)\) 种。

  直接把每个矩形哈希下来跑 BFS 即可。

  时间复杂度:\(O(nm^2)\)

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<map>
  5. #include<unordered_map>
  6. using namespace std;
  7. int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
  8. typedef long long ll;
  9. typedef pair<ll,ll> pll;
  10. const int N=10000;
  11. const int M=100000;
  12. const ll p=1000000007;
  13. const ll w1=127;
  14. const ll w2=129;
  15. ll fp(ll a,ll b)
  16. {
  17. ll s=1;
  18. for(;b;b>>=1,a=a*a%p)
  19. if(b&1)
  20. s=s*a%p;
  21. return s;
  22. }
  23. const ll inv1=fp(w1-1,p-2);
  24. const ll inv2=fp(w2-1,p-2);
  25. int min(int a,int b)
  26. {
  27. return a<b?a:b;
  28. }
  29. int max(int a,int b)
  30. {
  31. return a>b?a:b;
  32. }
  33. ll pw1[2][50000],pw2[2][50000];
  34. struct point{int x,y;};
  35. int n,m;
  36. point a[M];
  37. void init()
  38. {
  39. ll v=w1;
  40. for(int i=0;i<=1;i++)
  41. {
  42. pw1[i][0]=1;
  43. for(int j=1;j<=1<<15;j++)
  44. pw1[i][j]=pw1[i][j-1]*v%p;
  45. v=pw1[i][1<<15];
  46. }
  47. v=w2;
  48. for(int i=0;i<=1;i++)
  49. {
  50. pw2[i][0]=1;
  51. for(int j=1;j<=1<<15;j++)
  52. pw2[i][j]=pw2[i][j-1]*v%p;
  53. v=pw2[i][1<<15];
  54. }
  55. }
  56. ll pow1(ll x)
  57. {
  58. return pw1[1][x>>15]*pw1[0][x&((1<<15)-1)]%p;
  59. }
  60. ll pow_sum1(ll x)
  61. {
  62. return (pow1(x+1)-1)*inv1%p;
  63. }
  64. ll calc1(ll l,ll r)
  65. {
  66. return pow_sum1(r-l)*pow1(l)%p;
  67. }
  68. ll pow2(ll x)
  69. {
  70. return pw2[1][x>>15]*pw2[0][x&((1<<15)-1)]%p;
  71. }
  72. ll pow_sum2(ll x)
  73. {
  74. return (pow2(x+1)-1)*inv2%p;
  75. }
  76. ll calc2(ll l,ll r)
  77. {
  78. return pow_sum2(r-l)*pow2(l)%p;
  79. }
  80. struct rect
  81. {
  82. int xl,xr,yl,yr;
  83. rect(int a=0,int b=0,int c=0,int d=0):xl(a),xr(b),yl(c),yr(d){}
  84. };
  85. map<ll,ll> g;
  86. map<ll,int> c[32];
  87. rect d[100000];
  88. ll f[100000];
  89. ll h[100000];
  90. pll s[100000];
  91. int c22[100000];
  92. int c21[100000];
  93. int c11[100000];
  94. int c12[100000];
  95. int num;
  96. int __;
  97. ll insert(int xl,int xr,int yl,int yr,int x,ll v)
  98. {
  99. ll s=0;
  100. for(int i=1;i<=m;i++)
  101. {
  102. __++;
  103. int _=(i==m?1:i+1);
  104. if(a[i].y!=a[_].y||a[i].y>yr)
  105. continue;
  106. int x1=min(a[i].x,a[_].x);
  107. int x2=max(a[i].x,a[_].x);
  108. if(x1>xr||x2<xl)
  109. continue;
  110. int y1=max(a[i].y,yl);
  111. int y2=yr;
  112. x1<xl?x1=xl:0;
  113. x2>xr?x2=xr:0;
  114. if(a[i].x<a[_].x)
  115. s+=calc1(x1-xl,x2-xl-1)*calc2(y1-yl,y2-yl-1)%p;
  116. else
  117. s-=calc1(x1-xl,x2-xl-1)*calc2(y1-yl,y2-yl-1)%p;
  118. }
  119. s=(s%p+p)%p;
  120. int &o=c[x][s];
  121. if(!o)
  122. {
  123. num++;
  124. o=num;
  125. h[num]=s;
  126. d[num]=rect(xl,xr,yl,yr);
  127. }
  128. f[o]+=v;
  129. return o;
  130. }
  131. pll e[1000000];
  132. ll s1[1000000],s2[1000000];
  133. int t;
  134. int main()
  135. {
  136. #ifndef ONLINE_JUDGE
  137. freopen("b.in","r",stdin);
  138. freopen("b.out","w",stdout);
  139. #endif
  140. init();
  141. scanf("%d%d",&n,&m);
  142. for(int i=1;i<=m;i++)
  143. scanf("%d%d",&a[i].x,&a[i].y);
  144. int rt=insert(0,1<<n,0,1<<n,n,1);
  145. for(int i=n;i>=1;i--)
  146. {
  147. for(auto v:c[i])
  148. {
  149. int xl=d[v.second].xl;
  150. int xr=d[v.second].xr;
  151. int yl=d[v.second].yl;
  152. int yr=d[v.second].yr;
  153. ll _=f[v.second];
  154. int xmid=(xl+xr)>>1;
  155. int ymid=(yl+yr)>>1;
  156. c11[v.second]=insert(xl,xmid,yl,ymid,i-1,_);
  157. c12[v.second]=insert(xl,xmid,ymid,yr,i-1,_);
  158. c21[v.second]=insert(xmid,xr,yl,ymid,i-1,_);
  159. c22[v.second]=insert(xmid,xr,ymid,yr,i-1,_);
  160. }
  161. }
  162. fprintf(stderr,"%d\n",__);
  163. // return 0;
  164. for(int i=num;i>=1;i--)
  165. {
  166. int xl=d[i].xl;
  167. int xr=d[i].xr;
  168. int yl=d[i].yl;
  169. int yr=d[i].yr;
  170. ll area=ll(xr-xl)*(yr-yl);
  171. if(area==1)
  172. {
  173. if(h[i]==1)
  174. s[i]=pll(0,0);
  175. else
  176. s[i]=pll(-1,-1);
  177. continue;
  178. }
  179. pll s1,s2;
  180. pll s11=s[c11[i]],s12=s[c12[i]];
  181. if(s12.first==-1)
  182. s1=s11;
  183. else if(s11.first==-1)
  184. s1=pll(s12.first+area/4,s12.second+area/4);
  185. else
  186. {
  187. s12.first+=area/4;
  188. s12.second+=area/4;
  189. g[s12.first-s11.second-1]+=f[i];
  190. s1=pll(s11.first,s12.second);
  191. }
  192. pll s21=s[c21[i]],s22=s[c22[i]];
  193. if(s22.first==-1)
  194. s2=s21;
  195. else if(s21.first==-1)
  196. s2=pll(s22.first+area/4,s22.second+area/4);
  197. else
  198. {
  199. s22.first+=area/4;
  200. s22.second+=area/4;
  201. g[s22.first-s21.second-1]+=f[i];
  202. s2=pll(s21.first,s22.second);
  203. }
  204. if(s2.first==-1)
  205. s[i]=s1;
  206. else if(s1.first==-1)
  207. s[i]=pll(s2.first+area/2,s2.second+area/2);
  208. else
  209. {
  210. s2.first+=area/2;
  211. s2.second+=area/2;
  212. g[s2.first-s1.second-1]+=f[i];
  213. s[i]=pll(s1.first,s2.second);
  214. }
  215. }
  216. pll all=s[rt];
  217. g.erase(0);
  218. ll cnt=1,tot=all.second-all.first+1;
  219. for(auto v:g)
  220. {
  221. e[++t]=v;
  222. tot-=v.first*v.second;
  223. cnt+=v.second;
  224. }
  225. sort(e+1,e+t+1);
  226. for(int i=1;i<=t;i++)
  227. {
  228. s1[i]=s1[i-1]+e[i].second;
  229. s2[i]=s2[i-1]+e[i].first*e[i].second;
  230. }
  231. // return 0;
  232. int q;
  233. ll x;
  234. scanf("%d",&q);
  235. for(int i=1;i<=q;i++)
  236. {
  237. x=rd();
  238. if(x>=cnt)
  239. printf("%lld\n",tot);
  240. else
  241. {
  242. x=cnt-x;
  243. ll ans=tot;
  244. int y=upper_bound(s1+1,s1+t+1,x)-s1;
  245. ans+=s2[y-1];
  246. ans+=e[y].first*(x-s1[y-1]);
  247. printf("%lld\n",ans);
  248. }
  249. }
  250. return 0;
  251. }

【CERC2016】【BZOJ4792】村庄 搜索的更多相关文章

  1. P1171 售货员的难题--搜索(剪枝)

    题目背景 数据有更改 题目描述 某乡有nn个村庄(1<n \le 201<n≤20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0<s ...

  2. SQLSERVER走起微信公众帐号已经开通搜狗微信搜索

    SQLSERVER走起微信公众帐号已经开通搜狗微信搜索 请打开下面链接 http://weixin.sogou.com/gzh?openid=oIWsFt-hiIb_oYqQHaBMoNwRB2wM ...

  3. solr_架构案例【京东站内搜索】(附程序源代码)

    注意事项:首先要保证部署solr服务的Tomcat容器和检索solr服务中数据的Tomcat容器,它们的端口号不能发生冲突,否则web程序是不可能运行起来的. 一:solr服务的端口号.我这里的sol ...

  4. SQLServer地址搜索性能优化例子

    这是一个很久以前的例子,现在在整理资料时无意发现,就拿出来再改写分享. 1.需求 1.1 基本需求: 根据输入的地址关键字,搜索出完整的地址路径,耗时要控制在几十毫秒内. 1.2 数据库地址表结构和数 ...

  5. HTML5轻松实现搜索框提示文字点击消失---及placeholder颜色的设置

    在做搜索框的时候无意间发现html5的input里有个placeholder属性能轻松实现提示文字点击消失功能,之前还傻傻的在用js来实现类似功能... 示例 <form action=&quo ...

  6. bzoj1079--记忆化搜索

    题目大意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得 ...

  7. bzoj3208--记忆化搜索

    题目大意: 花花山峰峦起伏,峰顶常年被雪,Memphis打算帮花花山风景区的人员开发一个滑雪项目.    我们可以把风景区看作一个n*n的地图,每个点有它的初始高度,滑雪只能从高处往低处滑[严格大于] ...

  8. Android中通过ActionBar为标题栏添加搜索以及分享视窗

    在Android3.0之后,Google对UI导航设计上进行了一系列的改革,其中有一个非常好用的新功能就是引入的ActionBar,他用于取代3.0之前的标题栏,并提供更为丰富的导航效果.Action ...

  9. 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

随机推荐

  1. 使用 pm2 守护你的 .NET Core 应用程序

    一.守护进程的前世今生 守护进程,英文名:"daemon",也有守护神的意思.守护进程是一个在后台运行并且不受任何终端控制的进程,不会随着会话结束而退出.诸如 mysql.apac ...

  2. Manacher's Algorithm(马拉车算法)

    ## 背景 该算法用于求字符串的最长回文子串长度. ## 参考文章 >[最长回文子串——Manacher 算法](https://segmentfault.com/a/1190000003914 ...

  3. flex练习---纵横中文网

    采用 flexbox 弹性容器进行布局,只做练习用. 浏览器打开时切换到手机模式. 样本地址: http://tpl.zhuamimi.cn/%E6%89%8B%E6%9C%BA%E7%AB%AF%E ...

  4. 前端入门20-JavaScript进阶之异步回调的执行时机

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  5. 给萌新的Flexbox简易入门教程

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.sitepoint.com/flexbox-css-flexible-bo ...

  6. datatable的部分问题处理(动态定义列头,给某行添加事件,初始显示空数据)

    一.动态定义列头 在ajax中,用datatable再去重新配置列头,当然传回的数据中,要有对应放列头的键值对 我自定义了Mock数据,用于前端自己交互. 其中,rowdata用于存放传回的数据,co ...

  7. Swift中 删除Array的元素对象

    Swift中Array的删除对象 在Swift中数组Array没有removeObject的方法 1.找到下标 let model_index = selectedArray.index(where: ...

  8. Vue.js04:vue样式-通过属性绑定方式为元素设置class类样式

    <!-- 传统写法 --> <h1 class="red thin">这是一个h1标签</h1> <!-- 第一种使用方式,直接传递一个数 ...

  9. 【夯实shell基础】shell基础面面观

    本文地址 点击关注微信公众号 wenyuqinghuai 分享提纲: 1. shell中的函数 2. shell中的数组 3. shell中的变量 4. shell中的运算符 5. Linux的一些命 ...

  10. Storm入门(五)Twitter Storm如何保证消息不丢失

    转自:http://xumingming.sinaapp.com/127/twitter-storm如何保证消息不丢失/ storm保证从spout发出的每个tuple都会被完全处理.这篇文章介绍st ...