Problem 1 抓牛(catchcow.cpp/c/pas)

【题目描述】

农夫约翰被通知,他的一只奶牛逃逸了!所以他决定,马上出发,尽快把那只奶牛抓回来.

他们都站在数轴上.约翰在N(O≤N≤100000)处,奶牛在K(O≤K≤100000)处.约翰有两种办法移动,步行和瞬移:步行每秒种可以让约翰从x处走到x+l或x-l处;而瞬移则可让他在1秒内从x处消失,在2x处出现.然而那只逃逸的奶牛,悲剧地没有发现自己的处境多么糟糕,正站在那儿一动不动.

那么,约翰需要多少时间抓住那只牛呢?

【输入格式】

仅有两个整数N和K

【输出格式】

最短时间

【样例输入】

5 17

【样例输出】

4

【题解】

广搜水过

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #include <algorithm>
  6.  
  7. inline void read(int &x){x = ;char ch = getchar();char c = ch;while(ch > '' || ch < '')c = ch, ch = getchar();while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();if(c == '-')x = -x;}
  8. const int INF = 0x3f3f3f3f;
  9. const int MAXN = ;
  10.  
  11. int n,k;
  12. int b[MAXN][];
  13. //状态标号:0:x+1 1:x - 1 2:x * 2
  14. struct Node
  15. {
  16. int x,flag,step;
  17. }queue[];
  18. int head,tail;
  19. int ans;
  20.  
  21. inline void bfs()
  22. {
  23. //[head, tail]
  24. if(n >= k)
  25. {
  26. ans = n - k;return;
  27. }
  28. if((n + == k || n - == k) || ((n << ) == k))
  29. {
  30. ans = ;return;
  31. }
  32. head = , tail = ;
  33. queue[++tail] = Node{n - , , };
  34. queue[++tail] = Node{n + , , };
  35. queue[++tail] = Node{(n << ), , };
  36. b[n - ][] = true;
  37. b[n + ][] = true;
  38. b[(n << )][] = true;
  39. register Node tmp;
  40. while(head <= tail)
  41. {
  42. tmp = queue[head ++];
  43. for(int i = ;i < ;++ i)
  44. {
  45. if(i == && tmp.x - >= && !b[tmp.x - ][])
  46. {
  47. if(tmp.x - == k)
  48. {
  49. ans = tmp.step + ;
  50. return;
  51. }
  52. queue[++tail] = Node{tmp.x - , , tmp.step + };
  53. b[tmp.x - ][] = true;
  54. }
  55. else if(i == && tmp.x + <= && !b[tmp.x + ][])
  56. {
  57. if(tmp.x + == k)
  58. {
  59. ans = tmp.step + ;
  60. return;
  61. }
  62. queue[++tail] = Node{tmp.x + , , tmp.step + };
  63. b[tmp.x + ][] = true;
  64. }
  65. else if(tmp.x * <= && !b[(tmp.x << )][])
  66. {
  67. if((tmp.x << ) == k)
  68. {
  69. ans = tmp.step + ;
  70. return;
  71. }
  72. queue[++tail] = Node{(tmp.x << ), , tmp.step + };
  73. b[(tmp.x << )][] = true;
  74. }
  75. }
  76. }
  77. }
  78.  
  79. int main()
  80. {
  81. read(n);read(k);
  82. bfs();
  83. printf("%d", ans);
  84. return ;
  85. }

Problem 2 路面修整(grading.cpp/c/pas)

【题目描述】

FJ打算好好修一下农场中某条凹凸不平的土路。按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中。 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度。由于将每一段路垫高或挖低一个单位的花费相同,修路的总支出可以表示为: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 请你计算一下,FJ在这项工程上的最小支出是多少。FJ向你保证,这个支出不会超过2^31-1。【输入格式】
 第1行: 输入1个整数:N * 第2..N+1行: 第i+1行为1个整数:A_i

【输出格式】
第1行: 输出1个正整数,表示FJ把路修成高度不上升或高度不下降的最小花费

【样例输入】

7
1
3
2
4
5
3
9

【样例输出】

3

【样例解释】

FJ将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3| = 3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。

【题解】

DP题。

【状态定义】

dp[i][j]表示前i个数,最后一个数在原数组中是第j大/小的最小价值。记录cnt[i]为第i大/小得数,num[i]为第i个位置的数

【转移】
dp[i][j] = min{dp[i - 1][k] + abs(num[i] - cnt[j])} 1 <= k <= j

【优化】
1、状态更新是O(n)的,我们可以用mi[i][j]表示dp[i][1..j]的最小值
2、这里还有一个技巧,我们可以让dp[i][j]表示前i个数,最后一个数在原数组中是前j大 的最小价值
   转移有
   dp[i][j] = min{dp[i][j - 1], dp[i - 1][j] + abs(num[i] - cnt[j])} 
   同时也可以使用滚动数组进行优化

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #include <algorithm>
  6. inline int min(int a, int b){return a > b ? b : a;}
  7. inline void read(int &x){x = ;char ch = getchar();char c = ch;while(ch > '' || ch < '')c = ch, ch = getchar();while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();if(c == '-')x = -x;}
  8. const int INF = 0x3f3f3f3f;
  9. const int MAXN = + ;
  10.  
  11. int dp[][MAXN], num[MAXN], cnt[MAXN], recnt[MAXN],ans,n;
  12.  
  13. int main()
  14. {
  15. read(n);
  16. for(register int i = ;i <= n;++ i)
  17. {
  18. read(num[i]);
  19. recnt[i] = cnt[i] = num[i];
  20. }
  21. std::sort(cnt + , cnt + + n);
  22. std::sort(recnt + , recnt + + n, std::greater<int>());
  23. register int tmp = ;
  24. for(register int i = ;i <= n;++ i)
  25. {
  26. for(register int j = ;j <= n;++ j)
  27. {
  28. if(j == )
  29. dp[tmp][j] = dp[tmp ^ ][j] + abs(cnt[j] - num[i]);
  30. else
  31. dp[tmp][j] = min(dp[tmp][j - ], dp[tmp ^ ][j] + abs(cnt[j] - num[i]));
  32. }
  33. tmp ^= ;
  34. }
  35. ans = dp[n & ][n];
  36. tmp = ;
  37. for(register int i = ;i <= n;++ i)
  38. {
  39. for(register int j = ;j <= n;++ j)
  40. {
  41. if(j == )
  42. dp[tmp][j] = dp[tmp ^ ][j] + abs(recnt[j] - num[i]);
  43. else
  44. dp[tmp][j] = min(dp[tmp][j - ], dp[tmp ^ ][j] + abs(recnt[j] - num[i]));
  45. }
  46. tmp ^= ;
  47. }
  48. ans = min(ans, dp[n & ][n]);
  49. printf("%d", ans);
  50. return ;
  51. }

Problem 3 教主的魔法(magic.cpp/c/pas)

【题目描述】

教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。

每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)

CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。M”,则紧接着有三个数字L

WD巨懒,于是他把这个回答的任务交给了你。

【输入格式】

第1行为两个整数N、Q。Q为问题数与教主的施法数总和。

第2行有N个正整数,第i个数代表第i个英雄的身高。

第3到第Q+2行每行有一个操作:

(1)若第一个字母为“、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。

(2)若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。

【输出格式】

对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。

【样例输入】

5 3

1 2 3 4 5

A 1 5 4

M 3 5 1

A 1 5 4

【样例输出】

2

3

【数据范围】

【输入输出样例说明】

原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

【数据范围】

对30%的数据,N≤1000,Q≤1000。

对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000

【题解】

分块+二分模板题,第一次写分块。。常数优化到天际

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #include <algorithm>
  6. #include <cmath>
  7.  
  8. inline void read(int &x){x = ;char ch = getchar();char c = ch;while(ch > '' || ch < '')c = ch, ch = getchar();while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();if(c == '-')x = -x;}
  9. inline int min(int a, int b){return a < b ? a : b;}
  10. void put(int x){if (x < )x = ~x + , putchar('-');if (x > ) put(x / );putchar(x % + );}
  11. const int INF = 0x3f3f3f3f;
  12. const int MAXN = + ;
  13.  
  14. int n,q;
  15. int squ[MAXN],num[MAXN],pos[MAXN],block,flag[MAXN],size;
  16. int L[MAXN],R[MAXN];
  17.  
  18. //对第x个块进行重新排序
  19. int resort(int x)
  20. {
  21. int l = L[x];
  22. int r = R[x];
  23. for(register int i = l;i <= r;++ i)
  24. squ[i] = num[i];
  25. std::sort(squ + l, squ + r + );
  26. }
  27.  
  28. //对第x个块快内进行二分查找,返回找到的长度
  29. int find(int x, int k)
  30. {
  31. int l = L[x];
  32. int r = R[x];
  33. int last = r;
  34. int mid;
  35. while(l <= r)
  36. {
  37. mid = (l + r) >> ;
  38. if(squ[mid] < k)l = mid + ;
  39. else r = mid - ;
  40. }
  41. return last - l + ;
  42. }
  43.  
  44. //区间修改,[ll,rr]增加k
  45. inline void modify(int ll, int rr, int k)
  46. {
  47. //同一个块则暴力修改
  48. if(pos[ll] == pos[rr])
  49. {
  50. for(register int i = ll;i <= rr;++ i)
  51. num[i] = num[i] + k;
  52. resort(pos[ll]);
  53. return;
  54. }
  55.  
  56. //不同的块先改左右两边
  57. register int l = pos[ll],r = pos[rr];
  58. if(L[l] < ll)
  59. {
  60. for(register int i = ll;i <= R[l];++ i)
  61. num[i] = num[i] + k;
  62. resort(l);
  63. ++ l;
  64. }
  65. if(R[r] > rr)
  66. {
  67. for(register int i = L[r];i <= rr;++ i)
  68. num[i] = num[i] + k;
  69. resort(r);
  70. -- r;
  71. }
  72. for(register int i = l;i <= r;++ i)
  73. flag[i] = flag[i] + k;
  74. }
  75.  
  76. //区间查询,[ll,rr]查询k
  77.  
  78. int ask(int ll, int rr, int k)
  79. {
  80. register int ans = ;
  81. if(pos[ll] == pos[rr])
  82. {
  83. for(int i = ll;i <= rr;++ i)
  84. if(num[i] + flag[pos[i]] >= k)ans ++;
  85. return ans;
  86. }
  87. register int l = pos[ll],r = pos[rr];
  88. if(L[l] < ll)
  89. {
  90. for(register int i = ll;i <= R[l];++ i)
  91. if(num[i] + flag[pos[i]]>= k)ans ++;
  92. ++ l;
  93. }
  94. if(R[r] > rr)
  95. {
  96. for(register int i = L[r];i <= rr;++ i)
  97. if(num[i] + flag[pos[i]]>= k)ans ++;
  98. -- r;
  99. }
  100. for(register int i = l;i <= r;++ i)
  101. ans = ans + find(i, k - flag[i]);
  102. return ans;
  103. }
  104.  
  105. int main()
  106. {
  107. read(n);read(q);
  108.  
  109. register char c;
  110. register int tmp1,tmp2,tmp3;
  111.  
  112. block = sqrt(n);
  113. if(n % block)
  114. size = n / block + ;
  115. else
  116. size = n / block;
  117.  
  118. for(register int i = ;i <= n;++ i)
  119. {
  120. read(num[i]);
  121. pos[i] = (i - ) / block + ;
  122. squ[i] = num[i];
  123. }
  124. for(register int i = ;i <= size;++ i)
  125. L[i] = (i - ) * block + ,R[i] = i * block;
  126. if(R[size] > n)R[size] = n;
  127. for(register int i = ;i <= size;++ i)
  128. resort(i);
  129.  
  130. for(register int i = ;i <= q;++ i)
  131. {
  132. c = getchar();while(c != 'M' && c != 'A')c = getchar();
  133. read(tmp1);read(tmp2);read(tmp3);
  134. if(c == 'M')modify(tmp1, tmp2, tmp3);
  135. else put(ask(tmp1, tmp2, tmp3)), putchar('\n');
  136. }
  137. return ;
  138. }

NOIP模拟 7.03的更多相关文章

  1. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  2. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  3. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  4. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  5. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  6. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  7. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  8. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  9. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

随机推荐

  1. CAS企业级单点登录原理

    https://blog.csdn.net/anumbrella/article/details/80821486 1. 单点登录概述 1.1. 什么是单点登录? 单点登录:Single Sign O ...

  2. springMVC和springBoot区别

    Spring MVC是什么?(1)Spring MVC是Spring提供的一个强大而灵活的模块式web框架.通过Dispatcher Servlet, ModelAndView 和 View Reso ...

  3. Cat- Linux必学的60个命令

    1.作用 cat(“concatenate”的缩写)命令用于连接并显示指定的一个和多个文件的有关信息,它的使用权限是所有用户. 2.格式 cat [options] 文件1 文件2…… 3.[opti ...

  4. Centos7解决在同一局域网内无法使用ssh连接

    参考: https://www.cnblogs.com/liyuanhong/articles/5785368.html 一.修改网卡设置 nano /etc/sysconfig/network-sc ...

  5. SQL Server日常积累

    1:      在Sql Server 中增加一列语句:  alter table table_name add column_name [not null] [references ....]  例 ...

  6. typeof, offsetof, container_of宏

    container_of宏实现如下: #define container_of(ptr, type, member) ({ \ )->member ) *__mptr = (ptr); \ (t ...

  7. Spring注解驱动开发(二)-----生命周期、属性赋值

    bean的生命周期 bean的生命周期:bean创建---初始化----销毁的过程容器管理bean的生命周期:我们可以自定义初始化和销毁方法:容器在bean进行到当前生命周期的时候来调用我们自定义的初 ...

  8. [C#] 生成 (web): 未能加载文件或程序集“Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7

    有时候编译asp.net会遇到奇怪的错误: 生成 (web): 未能加载文件或程序集"Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, ...

  9. Jeecg-Boot 开发环境准备(二):开发工具安装

    目录索引: 后端开发工具 前端开发工具 Nodejs镜像 WebStorm入门配置 JeecgBoot采用前后端分离的架构,官方推荐开发工具 前端开发: Webstrom 或者 IDEA 后端开发: ...

  10. Luogu P4011 孤岛营救问题(状态压缩+最短路)

    P4011 孤岛营救问题 题意 题目描述 \(1944\)年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到 ...