Rudolf and k Bridges——Codeforces Round 933 (Div. 3) E

提交
题目大意 建一座桥要安装支架,支架之间的距离不能超过d(两个位置之间),建支架的代价是 a i j + 1 a_{ij}+1 aij+1 问建连续相邻的k座桥的最小代价是多少

分析
先求每座桥的代价,用前缀和算出连续k座(也可以用滑动窗口)
每座桥的代价如果用传统dp会超时,考虑优化,如果一个位置更加靠后且代价更小,是更优的,可以考虑用单调队列来维护,(维护一个单调递减队列),对于每个 a i j a_{ij} aij看是否和单调队列的距离满足d,满足的话计算价值添加到队列中,若不满足队头出队

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

int n,m,k,d;
void solve(){
    //如过一个点位置靠后,代价还小,那么更优
    //位置越来越远,代价越来越大,访问一个点
    //那这个点和他最近的那个那个支架,一定最前面满足位置空格
    //用单调队列维护
    cin>>n>>m>>k>>d;
    vector<vector<i64>> mp(n+1,vector<i64>(m+1));
    deque<i64> q;
    vector<i64> p;
    p.push_back(0);
    for(int i = 1;i<=n;++i){
        for(int j = 1;j<=m;++j){
            cin>>mp[i][j];
        }
    }

    for(int i = 1;i<=n;++i){
        deque<pair<i64,int>> dq;
        dq.push_back({1,1});
        for(int j =2;j<=m;++j){
            while(!dq.empty()&&j-dq.front().second-1>d) dq.pop_front();
            i64 v = dq.front().first+mp[i][j]+1;
            while(!dq.empty()&&dq.back().first>=v) dq.pop_back();
            dq.push_back({v,j});
        }
        p.push_back(dq.back().first);
    }
    i64 ans = 0x3f3f3f3f3f3f3f3f;
    for(int i = 1;i<=n;++i) p[i]+=p[i-1];
    for(int i = k;i<=n;++i) ans = min(ans,p[i]-p[i-k]);
    cout<<ans<<'\n';
}

signed main(){
    ios;
    int t;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值