Wannafly camp Day1 E Growth

题意

  二维坐标点(a, b),初始为0,每个时刻可以让a+1或b+1,。当a>=xi且b>=yi时,之后的每个时刻可以获得zi分。

  问m时刻后的最大分数。

  n <= 1000, m <= 2e9, x,y <= 1e9, z <= 1e6

题解

  考虑到有影响的x和y值只有给定的那些值,所以将x和y分别排序,用t[i][j]表示当a = xi, b = yi时能获得的奖励(对于有多组相同的x和y,对z求和),用v[i][j]表示当a = xi, b = yi时接下来每天能获得的奖励,即t[i][j]的二维前缀和。

  考虑DP,f[i][j]可以从i - 1, j和i, j - 1转移过来,方程为:f[i][j] = max(f[i - 1][j] + (x[i] - x[i - 1] - 1) * v[i - 1][j] + v[i][j], f[i][j - 1] + (y[j] - y[j - 1] - 1) * v[i][j - 1] + v[i][j])

  最后注意扫描找值时要加上剩下天数的贡献。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int x[1010], y[1010], xx[1010], yy[1010], z[1010];
 5 
 6 map<pair<int, int > , int> h;
 7 
 8 long long t[1010][1010], v[1010][1010];
 9 __int128 f[1010][1010];
10 
11 void print(__int128 x)
12 {
13     if (x>9) print(x/10);
14     putchar('0'+x%10);
15 }
16 
17 int main()
18 {
19     int n, m;
20     scanf("%d%d", &n, &m);
21     for (int i = 1; i <= n; ++i)
22     {
23         scanf("%d%d%d", &xx[i], &yy[i], &z[i]);
24         if (h[{xx[i], yy[i]}])
25             h[{xx[i], yy[i]}] += z[i];
26         else
27             h[{xx[i], yy[i]}] = z[i];
28     }
29     sort(xx + 1, xx + n + 1);
30     sort(yy + 1, yy + n + 1);
31     int X(0), Y(0);
32     x[++X] = xx[1];
33     y[++Y] = yy[1];
34     for (int i = 2; i <= n; ++i)
35     {
36         if (xx[i] != xx[i - 1])
37             x[++X] = xx[i];
38         if (yy[i] != yy[i - 1])
39             y[++Y] = yy[i];
40     }
41     for (int i = 1; i <= X; ++i)
42         for (int j = 1; j <= Y; ++j)
43             t[i][j] = h[{x[i], y[j]}];
44     for (int i = 1; i <= X; ++i)
45         for (int j = 1; j <= Y; ++j)
46             v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j];
47     for (int i = 1; i <= X; ++i)
48         for (int j = 1; j <= Y; ++j)
49             f[i][j] = max(f[i - 1][j] + (__int128)(x[i] - x[i - 1] - 1) * v[i - 1][j] + v[i][j], f[i][j - 1] + (__int128)(y[j] - y[j - 1] - 1) * v[i][j - 1] + v[i][j]);
50     __int128 ans(0);
51     for (int i = 1; i <= X; ++i)
52         for (int j = 1; j <= Y; ++j)
53             if (x[i] + y[j] <= m)
54                 ans = max(ans, f[i][j] + v[i][j] * (m - x[i] - y[j]));
55     print(ans);
56     putchar('
');
57 
58     return 0;
59 }
原文地址:https://www.cnblogs.com/aseer/p/9473980.html