求大佬看看解惑,30分
查看原帖
求大佬看看解惑,30分
784606
wuwendi123楼主2024/10/16 17:41
#include <bits/stdc++.h>
// 40
//    500 455 455 455 455 422 500 188 188 500 455 455 455 486 166 486 271 114 486 486 99 271 166 399 361 486 4 164 480 293 270 293 258 270 4 270 270 404 294 397 457 397 404 294 457 457 457 397 193 482 273 193 482 360 193
// dp  0   0   1   1   1   1   1   1   2   2   2   3   3   3   3   4   4   4   4   4  4   5   5   5   5   5  5  5   5   5   5   6   6   6  6  7   7   7   7   7  7    8   8   8   8   9   9   9   9  9    9  10   10  10  11
//思路,dp[i]代表以i结束的最长配对序列对数长度  (dp数组单调递增)
//tmp记录上一次凑对的是哪个数字   必须不能与上次相同
//  遍历数字,若第一次出现就不变,
// 若之前出现过  假设在左边第j位置
//     若能与上次的凑成一对(dp[j]+1 > dp[i-1)  则设置为dp[j]+1   更新tmp
//     若dp[j]+1 < dp[i-1]   说明上次位置凑出来并不优,还是保持原状
//    若dp[j]+1 == dp[i-1]   说明此时不管与j项合并还是保持原状,结果相同  tmp设置为-1   下次再出现成对的跟到谁后面均可
using namespace std;
const int N = 5e5+5;
int n,a[N],dp[N],tmp = -1,ans,maxx;
map<int,int> mp;  //记录位置
int main() {
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        // cout<<a[i]<<' ';
        // printf("%3d ",a[i]);
    }
    // cout<<endl;
    dp[0] = -9999;
    for(int i=1;i<=n;i++){
        if(mp.count(a[i])){
            if(a[i] != tmp ) {   //不能与上次相同
                int j = mp[a[i]];   //上一次出现的位置  
                if(dp[j] + 1 > dp[i-1]){
                    ans = dp[j] + 1;
                    tmp = a[i];
                    // mp[a[i]] = 0;
                }else if(dp[j] + 1 < dp[i-1]){
                    ans = dp[i-1];
                    // tmp = a[i-1];
                    // mp[a[i-1]] = 0;
                }else{
                    ans = dp[i-1];
                    tmp = -1;
                    // mp.clear();
                }
            }
        }
        dp[i] = ans;
        mp[a[i]]=i;  
        maxx = max(maxx,dp[i]);
        // printf("%3d ",tmp);
    }
     for(int i=1;i<=n;i++){
         cout<<dp[i]<<' ';
     }
    cout<<endl;
    
    cout<<maxx * 2;
    return 0;
}
2024/10/16 17:41
加载中...