传送门
题目描述
给出N个位子,排成一列,现在有M个烟花,每秒人的速度d,每个烟花有三个元素:a,b,t,表示在时刻t会绽放,如果我们在位子x观看到了的话,会获得b-abs(a-x)的欢乐值(可能为负而且所有烟花都必须观看);初始的时候可以在任何位子,问最高获得多少欢乐值。
分析
看完大概就知道需要DP搞一波
状态转移方程也比较好写
f[i][j] = max(f[i - 1][k] + b[i] - |a[i] - x|);
然后我们把b[i]提出来,可以转换成了求 |a[i] - x|的最小值。
k的范围应该是在x - dt * d ~ x + dt *d 之间,所以我们需要从1 - n跑一次,n - 1跑一次,每次记录一半区间内的最值
需要注意的是,[300][150000]的空间是明显开不下的,但是我们当前的状态仅需要上一维的状态进行状态转移,所以可以用类似于滚动数组的思想来优化空间
代码
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 152000;
const ll mod= 1000000007;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll f[N];
ll back[N];
ll q[N];
ll a[N],b[N],t[N];
ll sum;
ll d;
int n,m;
int main(){
read(n),read(m),read(d);
for(int i = 1;i <= m;i++){
read(a[i]),read(b[i]),read(t[i]);
sum += b[i];
}
for(int i = 1;i <= n;i++) f[i] = abs(i - a[1]);
for(int i = 2;i <= m;i++){
ll dt = t[i] - t[i - 1];
memcpy(back,f,sizeof f);
memset(f,0x3f,sizeof f);
int hh = 1,tt = 0;
for(int j = 1;j <= n;j++){
while(hh <= tt && q[hh] < j - dt * d) hh++;
while(hh <= tt && back[q[tt]] > back[j]) tt--;
q[++tt] = j;
f[j] = min(f[j],back[q[hh]] + abs(a[i] - j));
}
hh = 1,tt = 0;
for(int j = n;j;j--){
while(hh <= tt && q[hh] > j + dt * d) hh++;
while(hh <= tt && back[q[tt]] > back[j]) tt--;
q[++tt] = j;
f[j] = min(f[j],back[q[hh]] + abs(a[i] - j));
}
}
ll ans = 0x3f3f3f3f3f3f3f3f;
for(int i = 1;i <= n;i++) ans = min(ans,f[i]);
dl(sum - ans);
return 0;
}
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/