激光炸弹(二维前缀和)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <iostream> #include <cstring> #include <algorithm> #include <cmath>
typedef long long ll;
using namespace std;
const int N = 5000 + 10;
int n, r; int m1, m2; int sum[N][N]; int ans = 0;
int main() { cin >> n >> r; m1 = m2 = r; for (int i = 0; i < n; i++) { int x, y, w;
cin >> x >> y >> w; sum[++x][++y] += w; m1 = max(m1, x); m2 = max(m2, y); }
for (int i = 1; i <= m1; i++) for (int j = 1; j <= m2; j++) sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + sum[i][j]; for (int i = r; i <= m1; i++) { for (int j = r; j <= m2; j++) { ans = max(ans, sum[i][j] - sum[i][j - r] - sum[i - r][j] + sum[i - r][j - r]); } }
cout << ans << endl;
return 0; }
|
简单的二维前缀和,计算出所给数据的二维前缀和。
然后遍历半径为R的正方形的右下角,计算出最终的答案。
增减序列(差分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> #include <cmath> #include <algorithm> #include <cstring>
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
int n; int b[N];
int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> b[i]; for (int i = n; i >= 1; i--) b[i] -= b[i - 1];
ll pos = 0, neg = 0; for (int i = 2; i <= n; i++) { if (b[i] > 0) pos += b[i]; else neg -= b[i]; }
cout << min(pos, neg) + abs(pos - neg) << endl; cout << abs(pos - neg) + 1 << endl;
return 0; }
|
对区间进行操作,使用差分数组优化操作到O(1)。
结果要求所有数一样,即b[2]~b[n]=0。
每次操作如下:
- l = 1,r = n + 1:无意义
- l = 1,r = 2~n:改变b数组一个数(改变1无意义)
- l = 2~n,r = n + 1:改变b数组一个数(改变n+1无意义)
- l = 2
n,r = 2n(优先):改变b数组两个数,一个加、一个减。
我们可以统计正数和负数的个数,优先同时改变两个数。
剩余的数使用2或3操作进行改变,最终得到最小操作次数。
至于可能的情况,即改变b1的情况(使用2操作的可能次数)+不改变b1的情况(1种)。
最高的牛(差分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <iostream> #include <cmath> #include <algorithm> #include <cstring>
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
int n, p, h, m; int height[N]; bool visited[10000 + 10][10000 + 10];
int main() { cin >> n >> p >> h >> m; for (int i = 1; i <= m; i++) { int a, b;
cin >> a >> b; if (a > b) swap(a, b);
if (!visited[a][b]) { visited[a][b] = true; height[a + 1]--, height[b]++; } }
height[1] += h; for (int i = 1; i <= n; i++) { height[i] += height[i - 1]; cout << height[i] << endl; }
return 0; }
|
题目给出m对关系,即A和B可以相互看到。
给出最高的牛身高是h,求所有牛最大可能的身高。
给出A和B可以相互看到意味着:A和B之间的牛身高最大是min(A-1, B-1)。
不妨假设,初始所有牛身高为0。可以通过差分数组,每次让A和B之间牛的身高减一。
这样,通过前缀和可以计算出原身高相对关系。
然后在原身高的基础上加上最大的身高p,(p原来对应的是0)即可得到答案。