gym 100518 F. Funny Card Game

题解:dp[j][i]表示前i个数分了j块,pos[j][i]表第j块的起始位置在哪(即在哪个地方插入一个隔板)。

        转移方程: ①dp[j][i]可以从dp[j][i-1]转移过来,表示当前i这个位置的值贡献不是最优。

                           ②dp[j][i]从前面某个值相同的位置转移过来。对于值相同的的位置,可以再开一个数组ans[],与anspos[]分别记录最优值,与相应的最优值的位置。对于一个数值第一次出现而前面可能未预处理,所以每次预处理在dp前面。

#include"bits/stdc++.h"
using namespace std;
const int MX = 1e5+7;
const int INF = 1e9;
map<int,int> mp;
vector<int> res;
int a[MX];
int ans[MX], posans[MX];
int vis[MX], cnt[MX];
int dp[101][MX],pos[101][MX];

void upd(int &dp, int d, int &pos, int po)
{
    if(d > dp){
        dp = d;
        pos = po;
    }
}
int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#else
    freopen("funny.in","r",stdin);
    freopen("funny.out","w",stdout);
#endif // LOCAL
    int n,k;
    while(~scanf("%d%d",&n,&k)){
        if(n == 0 || k == 0) break;
        mp.clear();
        res.clear();
        int id = 0;
        for(int i = 1,x; i <= n; i++){
            scanf("%d",&x);
            if(mp.count(x)){
                a[i] = mp[x];
                vis[i] = ++cnt[mp[x]];
                continue;
            }
            a[i] = mp[x] = ++id;
            vis[i] = cnt[id] = 1;
        }

        for(int j = 1; j <= k; j++){
            for(int i = 0; i <= id; i++)
                ans[i] = -INF;

            int x = a[j];
            upd(ans[x],dp[j-1][j-1]-vis[j]+1, posans[x],j-1);
            dp[j][j] = j;
            pos[j][j] = j-1;
            for(int i = j+1; i <= n; i++){
                int x = a[i];
                dp[j][i] = dp[j][i-1];
                pos[j][i] = pos[j][i-1];
                upd(ans[x],dp[j-1][i-1]-vis[i]+1, posans[x],i-1);
                upd(dp[j][i],vis[i]+ans[x], pos[j][i],posans[x]);
//                cout<<j<<" "<<i<<" "<<dp[j][i]<<" "<<pos[j][i]<<endl;
            }
        }

        int p = pos[k][n];
        for(int j = k-1; j >= 1; j--){
            res.push_back(p);
            p = pos[j][p];
        }

        printf("%d\n",dp[k][n]);
        for(int i = res.size()-1; i >= 0; i--)
            printf("%d%c",res[i]," \n"[i==0]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_18869763/article/details/82262585
今日推荐