题目链接 微软大楼设计方案

中文题就不说题意了~

首先是简单版本

满足$1 <= n, m <= 50$

那么设$c[i][j]$为从第$i$幢楼到第$j$幢楼的最低的那幢楼的高度

计算两个点之间的距离的时候,若两个点分别在第$i$列,第$j$列,那么要根据$c[i][j]$来计算。

暴力即可

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7.  
  8. int n, k;
  9. int a[10010];
  10. int c[201][201];
  11. int x[201], y[201];
  12. int m;
  13. int ans = 0;
  14.  
  15. int main(){
  16.  
  17. scanf("%d%d", &n, &k);
  18. rep(i, 1, n) scanf("%d", a + i);
  19. rep(i, 1, n){
  20. c[i][i] = a[i];
  21. rep(j, i + 1, n) c[i][j] = min(c[i][j - 1], a[j]), c[j][i] = c[i][j];
  22. }
  23.  
  24. rep(i, 1, n) rep(j, 1, n) if (c[i][j] == 0) c[i][j] = c[j][i];
  25.  
  26. scanf("%d", &m);
  27.  
  28. rep(i, 1, m) scanf("%d%d", x + i, y + i);
  29.  
  30. rep(i, 1, m - 1){
  31. rep(j, i + 1, m){
  32. int cnt;
  33. if (y[i] > c[x[i]][x[j]] && y[j] > c[x[i]][x[j]])
  34. cnt = y[i] - c[x[i]][x[j]] + y[j] - c[x[i]][x[j]] + abs(x[i] - x[j]);
  35. else cnt = abs(x[i] - x[j]) + abs(y[i] - y[j]);
  36. if (cnt <= k) ++ans;
  37. }
  38. }
  39.  
  40. printf("%d\n", ans);
  41. return 0;
  42.  
  43. }

再是中等版本

满足$1 <= n <= 200000, 1 <= m <= 2000$

$m$的范围让我们还是可以在1秒钟之内两两枚举点对并完成统计

就是$c[i][j]$不能按照刚刚那个方法求了。

我们构建一张ST表,令$f[i][j]$为从$i$开始连续$2^{j}$个数的最小值

于是在$O(1)$内我们可以得到第$i$幢楼到第$j$幢楼的最低的那幢楼的高度

中等版本也解决了

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7.  
  8. int a[200030];
  9. int f[200030][22];
  10. int n, m, k;
  11. int ans = 0;
  12.  
  13. struct node{
  14. int x, y;
  15. void scan(){ scanf("%d%d", &x, &y);}
  16. friend bool operator < (const node &a, const node &b){
  17. return a.x == b.x ? a.y < b.y : a.x < b.x;
  18. }
  19. } p[3010];
  20.  
  21. inline int solve(int l, int r){
  22. int k = (int)log2((double)(r - l + 1));
  23. return min(f[l][k], f[r - (1 << k) + 1][k]);
  24. }
  25.  
  26. void work(){
  27. rep(i, 1, n) f[i][0] = a[i];
  28. rep(j, 1, 20) rep(i, 1, n)
  29. if ((i + (1 << j) - 1) <= n) f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
  30. }
  31.  
  32. int main(){
  33.  
  34. scanf("%d%d", &n, &k);
  35. rep(i, 1, n) scanf("%d", a + i);
  36.  
  37. work();
  38.  
  39. scanf("%d", &m);
  40. rep(i, 1, m) p[i].scan();
  41. sort(p + 1, p + m + 1);
  42.  
  43. rep(i, 1, m - 1){
  44. rep(j, i + 1, m){
  45. int cnt;
  46. int now = solve(p[i].x, p[j].x);
  47. if (p[i].y > now && p[j].y > now)
  48. cnt = p[i].y - now + p[j].y - now + abs(p[i].x - p[j].x);
  49. else cnt = abs(p[i].x - p[j].x) + abs(p[i].y - p[j].y);
  50. if (cnt <= k) ++ans;
  51. }
  52. }
  53.  
  54. printf("%d\n", ans);
  55. return 0;
  56.  
  57. }

最后是困难版本

满足$1 <= n <= 200000, 1 <= m <= 200000$

这个时候不能两两枚举点对来统计了

注意到$h[i] <= 20$,这是一个很重要的条件

对于当前在第$i$列的某个点,我们发现在他之后的$max(0, k - 40)$列中的所有点

这些点不用考虑,一定符合条件

因位距离最大值为$ k - 40 + max(h[i]) + max(h[j]) <= k$,所以一定符合条件

同理我们也发现,第$i + k$之后的点肯定不符合条件

那么我们只要枚举$i + max(0, k - 40) + 1$ 到 $i + k$ 这些列中的所有点就可以了

做的时候维护一个前缀和即可。

时间复杂度$O(mlogm + mh^{2})$

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7.  
  8. const int N = 200100;
  9.  
  10. int a[N];
  11. int f[N][22];
  12. int n, m, k;
  13. long long ans = 0;
  14. long long c[N];
  15. int g[N][22];
  16.  
  17. vector <int> v[N];
  18.  
  19. struct node{
  20. int x, y;
  21. void scan(){ scanf("%d%d", &x, &y);}
  22. friend bool operator < (const node &a, const node &b){
  23. return a.x == b.x ? a.y < b.y : a.x < b.x;
  24. }
  25. } p[N];
  26.  
  27. inline int solve(int l, int r){
  28. int k = (int)log2((double)(r - l + 1));
  29. return min(f[l][k], f[r - (1 << k) + 1][k]);
  30. }
  31.  
  32. void work(){
  33. rep(i, 1, n) f[i][0] = a[i];
  34. rep(j, 1, 20) rep(i, 1, n)
  35. if ((i + (1 << j) - 1) <= n) f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
  36. }
  37.  
  38. int main(){
  39.  
  40. scanf("%d%d", &n, &k);
  41.  
  42. rep(i, 1, n) scanf("%d", a + i);
  43.  
  44. work();
  45.  
  46. scanf("%d", &m);
  47. rep(i, 1, m) p[i].scan();
  48. sort(p + 1, p + m + 1);
  49. memset(g, 0, sizeof g);
  50.  
  51. rep(i, 1, m) ++c[p[i].x];
  52. rep(i, 1, n) c[i] += c[i - 1];
  53. rep(i, 1, m){
  54. v[p[i].x].push_back(i);
  55. g[p[i].x][p[i].y] = 1;
  56. }
  57.  
  58. rep(i, 1, m){
  59. rep(j, p[i].y + 1, a[p[i].x]) if (abs(j - p[i].y) <= k && g[p[i].x][j]) ++ans;
  60. int cnt = p[i].x + k - 40;
  61. if (cnt > n) cnt = n;
  62.  
  63. if (cnt > p[i].x){
  64. long long xx = c[cnt], yy = c[p[i].x];
  65. ans += xx - yy;
  66. }
  67.  
  68. int now = p[i].x + k;
  69. if (now > n) now = n;
  70.  
  71. rep(j, max(cnt + 1, p[i].x + 1), now){
  72.  
  73. for (auto u : v[j]){
  74. int cnt;
  75. int now = solve(p[i].x, p[u].x);
  76. if (p[i].y > now && p[u].y > now)
  77. cnt = p[i].y - now + p[u].y - now + abs(p[i].x - p[u].x);
  78. else cnt = abs(p[i].x - p[u].x) + abs(p[i].y - p[u].y);
  79.  
  80. if (cnt <= k) ++ans;
  81.  
  82. }
  83.  
  84. }
  85.  
  86. }
  87.  
  88. printf("%lld\n", ans);
  89. return 0;
  90.  
  91. }

计蒜客 微软大楼设计方案(RMQ)的更多相关文章

  1. 计蒜课/ 微软大楼设计方案/中等(xjb)

    题目链接:https://nanti.jisuanke.com/t/15772 题意:中文题诶- 思路:对于坐标为p1(x1, y1), p2(x2, y2) 的两个核心, 其中 x1 <= x ...

  2. 计蒜客 作弊揭发者(string的应用)

    鉴于我市拥堵的交通状况,市政交管部门经过听证决定在道路两侧安置自动停车收费系统.当车辆驶入车位,系统会通过配有的摄像头拍摄车辆画面,通过识别车牌上的数字.字母序列识别车牌,通过连接车管所车辆信息数据库 ...

  3. 计蒜客的一道题dfs

    这是我无聊时在计蒜客发现的一道题. 题意: 蒜头君有一天闲来无事和小萌一起玩游戏,游戏的内容是这样的:他们不知道从哪里找到了N根不同长度的木棍, 看谁能猜出这些木棍一共能拼出多少个不同的不等边三角形. ...

  4. 计蒜客模拟赛5 D2T1 成绩统计

    又到了一年一度的新生入学季了,清华和北大的计算机系同学都参加了同一场开学考试(因为两校兄弟情谊深厚嘛,来一场联考还是很正常的). 不幸的是,正当老师要统计大家的成绩时,世界上的所有计算机全部瘫痪了. ...

  5. 计蒜客 等边三角形 dfs

    题目: https://www.jisuanke.com/course/2291/182238 思路: 1.dfs(int a,int b,int c,int index)//a,b,c三条边的边长, ...

  6. 计蒜客 方程的解数 dfs

    题目: https://www.jisuanke.com/course/2291/182237 思路: 来自:https://blog.csdn.net/qq_29980371/article/det ...

  7. 计蒜客 买书 dfs

    题目: https://www.jisuanke.com/course/2291/182236 思路: 递归解决,从第一本书开始,每本书都有两种选择: //index是book里面每本书价格的下标, ...

  8. 计蒜客:Entertainment Box

    Ada, Bertrand and Charles often argue over which TV shows to watch, and to avoid some of their fight ...

  9. 爬虫acm比赛成绩(多页成绩整合在一起、获取复制不了的数据)(hihocoder、计蒜客)

    https://github.com/congmingyige/web-crawler_rank-of-competition-in-JiSuanKe-and-hihocoder 1. 计蒜客(获取复 ...

随机推荐

  1. RSA与AES实现数据加密传输

    RSA.AES简介 RSA:非对称加密,需要提前生成两个密钥(一对的),通过其中一个密钥加密后的数据,只有另一个密钥能解密.通常这两个密钥中有一个会暴漏出来,即对外公开的,这个密钥称为“公钥”,反之另 ...

  2. GoF23种设计模式之行为型模式之策略模式

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 1概述           定义一系列算法,把它们一个个都封装起来,并且让它们可以相互 ...

  3. poj 2718 切数问题 穷竭搜索

    题意: 给一个已经排序号的数字,从中间切一刀,成两个数,要求这两个数的差最小 思路:暴力比较差最小值 stl中的next_permutation()函数进行排列  注意:这个函数必须从小到大才可以排序 ...

  4. Linux操作系统启动流程

    一般来说,所有的操作系统的启动流程基本就是: 总的来说,linux系统启动流程可以简单总结为以下几步:1)开机BIOS自检,加载硬盘.2)读取MBR,进行MBR引导.3)grub引导菜单(Boot L ...

  5. 实践自己的WebSite______流水

    尝试从头至尾搭建一个MVC的网站,主要以流水的方式进行进度和记录,而不讨论技术的部分. 1,在Controller下创建两个文件夹,分别为sys和Business,分别对应于系统功能和业务逻辑.比如登 ...

  6. BZOJ 2465: [中山市选2009]小球

    难度在于读题 #include<cstdio> #include<algorithm> using namespace std; int a[1000005]; struct ...

  7. Netcore 基础之TagHelper知识

    饮水思源,来自:http://www.cnblogs.com/liontone 的BLOG中关于taghelper中的内容 概要 TagHelper是ASP.NET 5的一个新特性.也许在你还没有听说 ...

  8. JQuery 页面加载完成后执行事件

    一: $(document).ready(function(){ //code }) 二: jQuery(document).ready(function(){ //code }) 三: window ...

  9. 实施生成树 STP 高级

    一.生成树协议的演化 生成树协议可以识别防止二层环路 本节介绍每VLAN快速生成树增强版 PVRST+   和多生成树MST   如何配置协议   以及配置生成树系诶稳定性机制 1.生成树协议的演化 ...

  10. spring AOP详解四

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...