E. Yet Another Division Into Teams
阿新 • • 發佈:2020-08-05
Codeforces Round #598 (Div. 3)
思路
首先我們可以確定是選擇的team長度最長為5,因為如果是6的話我們很可能有更優的選擇權,而且當我們倒著弄\(i->i+2\quad i->i+3\quad i->i+4\)是可以遍歷每一種可能的。
在遍歷的過程中我們在\(minn\)陣列中存了每個團隊的上界和下界,比如說\(minn[i+3]=i\),那麼就是\(i->i+3\)
便於我們後期給\(ans\)陣列賦答案。
轉移方程:
\[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 \]
每次可能比上一次優就更新。
#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(); // } }