SB贪心......暴露了我代码能力巨弱的本质。
解:首先我们应该想到DP(但是我想到了贪心......)
然后分析题目本质,每个点有个限制,最早开走时间不得早于最晚上车时间。
然后我们就可以把每个人看做都在那个时间上车。
然后我们发现,对一个地方使用加速,会影响它后面一段区间。
然后就有个暴力·雏形是枚举在某个点用加速,看它能够减少的时间,取最大的那个用。
然后看一眼数据范围,大概是n²,可以过,只要你每次找到收益最大的点是O(n)即可。
然后发现好难写,细节巨多无比......一直觉得这个算法是错的,因为只有一个想法,根本无法转成代码实现。
然后肝了好久,受不了了,去看题解,发现我TM想的是正解,只是不会实现......
代码实现:
固定数组:limit,up,down,sum,分别表示最晚上车时间,上车人数,下车人数,down的前缀和。
变化数组:dis,to,to_lar,now,influ,分别表示所用时间(D),最远能影响到的位置,这条影响链上最多能承受减去的时间,抵达这里的时间,这里修改会影响的人数。
大部分可变数组都倒序求出,now是正序求出。
然后试一下某hack数据:
4 5 1
3 0 2
0 1 2
0 1 4
0 1 4
0 1 4
0 1 4 ans = 18
1 #define wwx AK_IOI 2 3 #include <cstdio> 4 #include <algorithm> 5 6 const int N = 1010, INF = 0x7f7f7f7f, M = 10010; 7 8 struct Custom { 9 int t, A, B; 10 }a[M]; 11 12 int n, m, k, dis[N], limit[N], to[N], now[N], up[N], down[N], sum[N], influ[N], to_lar[N]; 13 14 int main() { 15 scanf("%d%d%d", &n, &m, &k); 16 for(int i = 1; i < n; i++) { 17 scanf("%d", &dis[i]); 18 } 19 for(int i = 1; i <= m; i++) { 20 scanf("%d%d%d", &a[i].t, &a[i].A, &a[i].B); 21 limit[a[i].A] = std::max(limit[a[i].A], a[i].t); 22 up[a[i].A]++; 23 down[a[i].B]++; 24 } 25 sum[1] = down[1]; 26 for(int i = 2; i <= n; i++) { 27 limit[i] = std::max(limit[i], limit[i - 1]); 28 sum[i] = sum[i - 1] + down[i]; 29 } 30 // get limit sum up down 31 32 while(k) { 33 now[1] = 0; 34 for(int i = 2; i <= n; i++) { 35 now[i] = std::max(now[i - 1], limit[i - 1]) + dis[i - 1]; 36 } 37 int large = -1, pos = -1; 38 to[n] = n - 1; 39 to_lar[n] = INF; 40 for(int i = n - 1; i >= 1; i--) { 41 if(now[i + 1] > limit[i + 1]) { 42 to[i] = to[i + 1]; 43 to_lar[i] = std::min(to_lar[i + 1], now[i + 1] - limit[i + 1]); 44 //to_lar[i] = std::min(to_lar[i], dis[i]); <- ERROR 45 } 46 else { 47 to[i] = i; 48 to_lar[i] = INF; 49 } 50 influ[i] = sum[to[i] + 1] - sum[i]; 51 //printf("influ : %d %d ", i, influ[i]); 52 if(influ[i] > large && to_lar[i] && dis[i]) { 53 large = influ[i]; 54 pos = i; 55 } 56 } 57 if(to_lar[pos] == 0) { 58 break; 59 } 60 to_lar[pos] = std::min(to_lar[pos], dis[pos]); 61 dis[pos] -= std::min(to_lar[pos], k); 62 k -= std::min(to_lar[pos], k); 63 //printf("pos = %d to[] = %d lar = %d ", pos, to[pos], to_lar[pos]); 64 } 65 66 now[1] = 0; 67 for(int i = 2; i <= n; i++) { 68 now[i] = std::max(now[i - 1], limit[i - 1]) + dis[i - 1]; 69 } 70 71 int ans = 0; 72 for(int i = 1; i <= m; i++) { 73 ans += now[a[i].B] - a[i].t; 74 } 75 76 printf("%d", ans); 77 return 0; 78 }