酱神去杭州赏花。
花展在一条街道上举行,这条街道上有一共有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 ",ans); 56 } 57 return 0; 58 } 59 /* 60 30 3 2 61 27 3 1 62 11 4 1 63 11 4 1 64 */