酱神赏花

 

酱神去杭州赏花。

花展在一条街道上举行,这条街道上有一共有n个节点,自左而右从1到n编号,1号和n号是左右两个端点,两个相邻端点之间的距离为1.本次花展一共要展出m朵花,在第ti时刻,有一朵颜值为bi的花将在第ai个节点展出,如果酱神在ti时刻处于第x个节点,那么他能获得的开心值为bi−|x−ai|,注意这个值可能为负。

在t=1的时刻,酱神可以随意从1到n选出一个节点作为赏花的起点。在接下来的每个单位时间段中,酱神最多能移动d的距离。酱神每秒只能移动整数个距离,且任何时刻不能超出街道的范围。

他能获得的最大开心值为多少?

Input
第一行3个数n,m,d。

接下来m行,每行3个数ai,bi,ti。

1≤n≤105,1≤m≤100
1≤ai≤n
1≤bi≤109
1≤ti≤109
1≤d≤109
Output
输出一个数,酱神的最大开心值。

Sample Input
30 4 2
27 3 1
11 4 1
11 4 1
1 2 20
Sample Output
-3

 

 

// 显然是个dp题,dp状态很容易想到, dp[i][j] 代表在 i 位置赏前 j 朵花的最大开心度,

将花开时间排序后

dp[i][j] = max ( dp[i +- 开花间隙时间*d ][(j-1)&1] )

对于这个,如果暴力的话,会超时,用单调栈优化,将找max的时间优化了,这是第一次写这个,看了思路就自己写了,用了不少时间debug。。。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define INF 0x3f3f3f3f3f3f3f3fll
 5 #define MX 100005
 6 struct Flo
 7 {
 8     int a,b,t;
 9     bool operator < (const Flo& b)const
10     {
11         return t<b.t;
12     }
13 }flw[MX];
14 
15 int n,m,d;
16 LL dp[MX][2]; //gun dong buf
17 int sta[MX];
18 
19 int main()
20 {
21     while (scanf("%d%d%d",&n,&m,&d)!=EOF)
22     {
23         for (int i=1;i<=m;i++)
24             scanf("%d%d%d",&flw[i].a,&flw[i].b,&flw[i].t);
25         sort(flw+1,flw+1+m);
26 
27         for (int i=1;i<=n;i++)
28             dp[i][1]=flw[1].b-abs(i-flw[1].a);
29 
30         for (int j=2;j<=m;j++)
31         {
32             LL limit =(flw[j].t-flw[j-1].t)*d;
33             int l=1,r=1;
34             for (int k=1;k<=limit;k++)    //对于 i=1 直接先准备好单调栈
35             {
36                 if (k>n) break;     //这个地方搞得我 debug 很久
37                 while (l<r&&dp[k][(j+1)&1]>=dp[sta[r-1]][(j+1)&1]) r--;
38                 sta[r]=k; r++;
39             }
40             for (int i=1;i<=n;i++)
41             {
42                 while (l<r&&i+limit<=n&&dp[i+limit][(j+1)&1]>=dp[sta[r-1]][(j+1)&1]) r--; //尾部小的出栈
43                 if (i+limit<=n) //进栈
44                 {
45                     sta[r]=i+limit;
46                     r++;
47                 }
48                 while (l<r&&abs(i-sta[l])>limit) l++; //取合适的栈底元素
49                 dp[i][j&1] = dp[sta[l]][(j+1)&1]+flw[j].b-abs(i-flw[j].a);
50             }
51         }
52         LL ans = -INF;
53         for (int i=1;i<=n;i++)
54             ans = max (ans,dp[i][m&1]);
55         printf("%lld\n",ans);
56     }
57     return 0;
58 }
59 /*
60 30 3 2
61 27 3 1
62 11 4 1
63 11 4 1
64 */
View Code

 

 

 

posted @ 2017-05-27 10:22  happy_codes  阅读(158)  评论(0编辑  收藏  举报