洛谷P1315 观光公交

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  \n", 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 \n", 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 }
AC代码

 

posted @ 2018-10-17 13:09  huyufeifei  阅读(164)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜