逆天AC做法求hack
查看原帖
逆天AC做法求hack
1112954
lsc72楼主2024/11/13 21:45

先上代码

#include<bits/stdc++.h> 
using namespace std; 
#define ll long long 
#define pb push_back
const int MAXN=7020; 
int a[MAXN],n,T;
ll dp[MAXN][MAXN];
int p,q[MAXN],l,r;
int main(){ 
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); 
    cin>>T;
    while (T--){
        cin>>n; for (int i=1;i<=n;i++) cin>>a[i];
        for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) dp[i][j]=1e17;
        for (int i=1;i<n;i++) dp[i][i+1]=a[i];
        for (int k=3;k<=n;k++){
            l=1; r=0; p=1;
            for (int i=k;i<=n;i++){
                while (p<=i&&dp[i-k+1][p]<dp[p+1][i]) {
                    while (l<=r&&a[p]+dp[p+1][i]<=a[q[l]]+dp[q[l]+1][i]) l++;
                    q[++r]=p; p++;
                }
                while (l<=r&&q[l]<=i-k) l++;
                if (p<=i)dp[i-k+1][i]=min(dp[i-k+1][i],a[p]+dp[i-k+1][p]);
                if (l<=r) dp[i-k+1][i]=min(dp[i-k+1][i],a[q[l]]+dp[q[l]+1][i]);
            }
        }
        cout<<dp[1][n]<<'\n';
    }
    return 0;
} 

我好像是按照区间大小进行DP,然后前一部分的思路和题解差不多。
后一部分就很抽象了,维护后半部分答案大于前半部分答案的断点,因为i在增大,所以断点的后半部分答案会继续变大。关键是我是从队尾退决策,再从队尾补决策。
然后这个做法AC了,求hack+可能的解释?

2024/11/13 21:45
加载中...