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('\n'); 57 58 return 0; 59 }