CF372C

思路

根据题意可以得到dp转移方程是 \(f_{i,j}=\max\{f_{i-1,k}+b_i-|a_i-j|\}\)
而且 \(j-(t_{i}-t_{i-1})\times d\le k\le j+(t_{i}-t_{i-1})\times d\)
显然直接转移会超时
考虑用单调队列优化,优化的时候要注意相邻两个状态的左右区间要保持非下降的关系
代码

//                  ξ†(ᗜ ˰ ᗜ)†ξ
//           去吧,鸭鸭,把希儿和AC都带回来!
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N = 2e5 + 5;
int dp[2][N];
int q[N];
int a[305],b[305],t[305];
int n,m,d;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
    }
inline void print(int x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)
        print(x/10);
        putchar(x%10+'0');
    }
void solve(){
    int flag = 1;
    for(int i = 1; i <= m; i++){
        int l = 1,r = 0,k = 1;
        for(int j = 1; j <= n; j++){
            
            for(;k <= min(n,j + (t[i] - t[i-1]) * d);k++){
                while(l <= r && dp[flag^1][q[r]] <= dp[flag^1][k]) r--;
                q[++r] = k;
            }
            while(l <= r && q[l] < max((long long)1,j - (t[i]-t[i-1])*d)) l++;
            dp[flag][j] = dp[flag^1][q[l]] + b[i] - abs(a[i] - j);
            
        }
        flag ^= 1;
    }
    int ans = -1e18;
    for(int i = 1; i <= n; i++) ans = max(ans,dp[flag^1][i]);
    cout << ans << endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m >> d;
    for(int i = 1; i <= m; i++) cin >> a[i] >> b[i] >> t[i];
    solve();
    return 0;
}
//题目所考察知识:
//心得体会:
posted @ 2022-09-15 11:55  Sun-Wind  阅读(27)  评论(0编辑  收藏  举报