codeforces 721E Road to Home

题目链接:http://codeforces.com/contest/721/problem/E

----------------------------------------------------------------------------------

比赛的时候只想了一个初步的贪心思路后就直接用优先队列$+DP$乱搞了

这样做的话冗余的状态数是非常多的 最后果然$FST(TLE)$了

----------------------------------------------------------------------------------

比赛后一直在纠结有没有什么贪心的思路可以减少状态数的

然后发现其实我们只需要记录

对于每一段光照区间 利用完这个区间后的最多唱歌次数 如果有多个满足的再记录最左的位置

这样状态数就只有$O(n)$的级别了

再来考虑转移的时候是否具有单调性 稍稍想想就能发现这一部分直接写一个单调队列就好

最后总的复杂度是$O(n)$的

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 10;
 4 int qdist[N], qans[N];
 5 int l, n, p, t;
 6 void update(int x, int y, int &tdist, int &tans, int d, int a)
 7 {
 8     int cnt = (y - max(x, d + t)) / p;
 9     a += cnt;
10     d = max(x, d + t) + cnt * p;
11     if(a > tans || (a == tans && d < tdist))
12     {
13         tans = a;
14         tdist = d;
15     }
16 }
17 int main()
18 {
19     scanf("%d%d%d%d", &l, &n, &p, &t);
20     int front = 0, tail = 0, ans = 0;
21     qdist[tail] = -t;
22     qans[tail] = 0;
23     ++tail;
24     int x, y, tdist, tans;
25     while(n--)
26     {
27         scanf("%d%d", &x, &y);
28         tdist = y;
29         tans = 0;
30         front = max(front - 1, 0);
31         while(front < tail)
32         {
33             if(qdist[front] + t + p > y)
34                 break;
35             update(x, y, tdist, tans, qdist[front], qans[front]);
36             ++front;
37         }
38         if(ans < tans)
39         {
40             ans = tans;
41             qdist[tail] = tdist;
42             qans[tail] = tans;
43             ++tail;
44         }
45      }
46      printf("%d\n", ans);
47     return 0;
48 }

 

posted @ 2016-10-01 14:05  sagitta  阅读(785)  评论(3编辑  收藏  举报