激光炸弹

地图上有 0x03 前缀和与差分 - 图1 个目标,用整数 0x03 前缀和与差分 - 图2 表示目标在地图上的位置,每个目标都有一个价值 0x03 前缀和与差分 - 图3
注意:不同目标可能在同一位置。
现在有一种新型的激光炸弹,可以摧毁一个包含 0x03 前缀和与差分 - 图4 个位置的正方形内的所有目标。
激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 0x03 前缀和与差分 - 图5 轴平行。
求一颗炸弹最多能炸掉地图上总价值为多少的目标。

输入格式
第一行输入正整数 0x03 前缀和与差分 - 图60x03 前缀和与差分 - 图7,分别代表地图上的目标数目和正方形的边长,数据用空格隔开。
接下来 0x03 前缀和与差分 - 图8 行,每行输入一组数据,每组数据包括三个整数 0x03 前缀和与差分 - 图9,分别代表目标的 0x03 前缀和与差分 - 图10 坐标,0x03 前缀和与差分 - 图11 坐标和价值,数据用空格隔开。

输出格式
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。

数据范围
0x03 前缀和与差分 - 图12
0x03 前缀和与差分 - 图13,
0x03 前缀和与差分 - 图14
0x03 前缀和与差分 - 图15

输入样例:

  1. 2 1
  2. 0 0 1
  3. 1 1 1

输出样例:

  1. 1
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int N = 10010, M = 5050;
  5. int n, r, x, y, w;
  6. int s[M][M];
  7. int get(int x, int y, int x0, int y0) {
  8. return s[x0][y0] - s[x0][y-1] - s[x-1][y0] + s[x-1][y-1];
  9. }
  10. int main(){
  11. scanf("%d%d", &n, &r);
  12. int mx = 0, my = 0;
  13. for(int i=1;i<=n;i++){
  14. scanf("%d%d%d", &x, &y, &w);
  15. x ++; y ++;
  16. mx = max(mx, x); my = max(my, y);
  17. s[x][y] += w;
  18. }
  19. for(int i=1;i<=mx;i++) for(int j=1;j<=my;j++) s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
  20. int rs = 0;
  21. for(int i=1;i<=mx;i++) for(int j=1;j<=my;j++){
  22. int x = max(1, i - r + 1), y = max(1, j - r + 1);
  23. rs = max(rs, get(x, y, i, j));
  24. }
  25. printf("%d\n", rs);
  26. return 0;
  27. }

增减序列

给定一个长度为 0x03 前缀和与差分 - 图16 的数列 0x03 前缀和与差分 - 图17,每次可以选择一个区间 0x03 前缀和与差分 - 图18,使下标在这个区间内的数都加一或者都减一。
求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。
输入格式
第一行输入正整数 0x03 前缀和与差分 - 图19
接下来 0x03 前缀和与差分 - 图20 行,每行输入一个整数,第 0x03 前缀和与差分 - 图21 行的整数代表 0x03 前缀和与差分 - 图22

输出格式
第一行输出最少操作次数。
第二行输出最终能得到多少种结果。

数据范围
0x03 前缀和与差分 - 图23,
0x03 前缀和与差分 - 图24

输入样例:

  1. 4
  2. 1
  3. 1
  4. 2
  5. 2

输出样例:

  1. 1
  2. 2

此题是 铺设道路 的进阶版。
设 a 序列的差分序列为 b 序列。那么一次a区间加或者区间减对应b数组中的两个单点运算。
b[i] = a[i] - a[i-1],那么应当有 0x03 前缀和与差分 - 图25

  • 区间加:0x03 前缀和与差分 - 图26
  • 区间减:0x03 前缀和与差分 - 图27

所以,只要计算出 0x03 前缀和与差分 - 图28中正数的和 p 以及 负数的绝对值和 q,就可以得到答案。
当然 p 和 q 的数量可能不同,设 x = abs(p - q),那么这 x 次区间操作,可以选择一部分修改 b[1], 也可以修改 b[n + 1]。
不难想到,最少操作数是 max(p, q)。
如果选择修改 b[1],则相当于改变最终数组中所有数值的大小。所以共有 x + 1 种方案。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100010;
  4. typedef long long ll;
  5. int n;
  6. ll a[N];
  7. int main(){
  8. scanf("%d", &n);
  9. for(int i=1;i<=n;i++) scanf("%lld", &a[i]);
  10. ll p = 0, q = 0;
  11. for(int i=2;i<=n;i++){
  12. ll c = a[i] - a[i-1];
  13. if(c > 0) p += c;
  14. else q -= c;
  15. }
  16. ll rs1 = max(p, q), rs2 = abs(p - q) + 1;
  17. printf("%lld\n%lld\n", rs1, rs2);
  18. return 0;
  19. }

最高的牛

0x03 前缀和与差分 - 图29 头牛站成一行,被编队为 0x03 前缀和与差分 - 图30,每头牛的身高都为整数。
当且仅当两头牛中间的牛身高都比它们矮时,两头牛方可看到对方。
现在,我们只知道其中最高的牛是第 0x03 前缀和与差分 - 图31 头,它的身高是 0x03 前缀和与差分 - 图32 ,剩余牛的身高未知。
但是,我们还知道这群牛之中存在着 0x03 前缀和与差分 - 图33 对关系,每对关系都指明了某两头牛 0x03 前缀和与差分 - 图340x03 前缀和与差分 - 图35 可以相互看见。
求每头牛的身高的最大可能值是多少。

输入格式
第一行输入整数 0x03 前缀和与差分 - 图36,数据用空格隔开。
接下来 0x03 前缀和与差分 - 图37 行,每行输出两个整数 0x03 前缀和与差分 - 图380x03 前缀和与差分 - 图39 ,代表牛 0x03 前缀和与差分 - 图40 和牛 0x03 前缀和与差分 - 图41 可以相互看见,数据用空格隔开。

输出格式
一共输出 0x03 前缀和与差分 - 图42 行数据,每行输出一个整数。
0x03 前缀和与差分 - 图43 行输出的整数代表第 0x03 前缀和与差分 - 图44 头牛可能的最大身高。

数据范围
0x03 前缀和与差分 - 图45,
0x03 前缀和与差分 - 图46,
0x03 前缀和与差分 - 图47,
0x03 前缀和与差分 - 图48

输入样例:

  1. 9 3 5 5
  2. 1 3
  3. 5 3
  4. 4 3
  5. 3 7
  6. 9 8

输出样例:

  1. 5
  2. 4
  3. 5
  4. 3
  5. 4
  6. 4
  7. 5
  8. 5
  9. 5

此题中给出的关系对可能存在重复
首先忽略掉第 p 头牛的身高 H,仅仅计算每头牛的身高差。
如果存在一对关系 ,那么 c[a + 1] —, c[b] ++。
最后所有的 c 应当加上 h - c[p]。
输入时,关系会重复出现,所以要去重。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define rep(i,j,k) for(int i=int(j);i<=int(k);i++)
  4. #define per(i,j,k) for(int i=int(j);i>=int(k);i--)
  5. typedef long long ll;
  6. const int N = 10010;
  7. int n, p, h, m;
  8. int c[N];
  9. unordered_map<int, int> mp;
  10. int main(){
  11. scanf("%d%d%d%d", &n, &p, &h, &m);
  12. rep(i,1,m) {
  13. int a, b;scanf("%d%d", &a, &b);
  14. if(a > b) swap(a, b);
  15. int x = a * 10000 + b;
  16. if(mp.count(x)) continue;
  17. mp[x] = 1;
  18. c[a + 1] --; c[b] ++;
  19. }
  20. rep(i,1,n) c[i] += c[i-1];
  21. int x = h - c[p];
  22. rep(i,1,n) c[i] += x;
  23. rep(i,1,n) printf("%d\n",c[i]);
  24. return 0;
  25. }