E. Yet Another Division Into Teams

Codeforces Round #598 (Div. 3)

思路

首先我们可以确定是选择的team长度最长为5,因为如果是6的话我们很可能有更优的选择权,而且当我们倒着弄 i − > i + 2 i − > i + 3 i − > i + 4 i->i+2\quad i->i+3\quad i->i+4 i>i+2i>i+3i>i+4是可以遍历每一种可能的。

在遍历的过程中我们在 m i n n minn minn数组中存了每个团队的上界和下界,比如说 m i n n [ i + 3 ] = i minn[i+3]=i minn[i+3]=i,那么就是 i − > i + 3 i->i+3 i>i+3

便于我们后期给 a n s ans ans数组赋答案。

转移方程:
d p [ i + 2 ] = d p [ i − 1 ] + n o d e [ i + 2 ] . v − n o d e [ i ] . v d p [ i + 3 ] = d p [ i − 1 ] + n o d e [ i + 3 ] . v − n o d e [ i ] . v d p [ i + 4 ] = d p [ i − 1 ] + n o d e [ i + 4 ] . v − n o d e [ i ] . v dp[i+2]=dp[i-1]+node[i+2].v-node[i].v\\ dp[i+3]=dp[i-1]+node[i+3].v-node[i].v\\dp[i+4]=dp[i-1]+node[i+4].v-node[i].v dp[i+2]=dp[i1]+node[i+2].vnode[i].vdp[i+3]=dp[i1]+node[i+3].vnode[i].vdp[i+4]=dp[i1]+node[i+4].vnode[i].v
每次可能比上一次优就更新。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(case, x) cout << case << "  : " << x << endl
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO                       \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)
#define pb push_back
using namespace std;
// #define int long long
#define lson rt << 1
#define rson rt << 1 | 1
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 2e5 + 10;

int dp[maxn],ans[maxn],minn[maxn];
struct node{
    int v,pos;
    bool operator<(const node x)const{
        return v<x.v;
    }
}node[maxn];

void solve() {
    int n;cin>>n;
    for(int i=1;i<=n;++i){
        cin>>node[i].v;
        node[i].pos=i;
    }
    sort(node+1,node+1+n);
    for(int i=1;i<=n;++i){
        dp[i]=1e9;
    }

    for(int i=1;i<=n;++i){
        if(i+3<=n+1){
            if(dp[i+2]>=dp[i-1]+node[i+2].v-node[i].v)
                dp[i+2]=dp[i-1]+node[i+2].v-node[i].v,minn[i+2]=i;
        }
        if(i+4<=n+1){
            if(dp[i+3]>=dp[i-1]+node[i+3].v-node[i].v)
                dp[i+3]=dp[i-1]+node[i+3].v-node[i].v,minn[i+3]=i;
        }
        if(i+5<=n+1){
            if(dp[i+4]>=dp[i-1]+node[i+4].v-node[i].v)
                dp[i+4]=dp[i-1]+node[i+4].v-node[i].v,minn[i+4]=i;
        }
    }
//    for(int i=1;i<=n;++i){
//        debug(i,dp[i]);
//    }
    int tot=0;
    int now=n;
    while(now!=0){
        ++tot;
        for(int i=now;i>=minn[now];--i)
            ans[node[i].pos]=tot;
        now=minn[now]-1;
    }
    cout<<dp[n]<<' '<<tot<<endl;
    for(int i=1;i<=n;++i){
        cout<<ans[i]<<' ';
    }

}

int main() {
//    int t;
//    cin >> t;
//    while(t--) {
        solve();
//    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值