求助
查看原帖
求助
654281
reclusive楼主2023/8/18 08:15

为什么这道题维护下凸壳可以AC

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5,M=255;
LL s[N],f[N][M];
int l,r,Q[N],ans[N][M];
long double X(int j){return s[j];}
long double Y(int j,int k){return (f[j][k-1]-s[j]*s[j]);}
long double slop(int j1,int j2,int k){
    if(X(j1)==X(j2))return -1e18;
    return (Y(j2,k)-Y(j1,k))/(X(j1)-X(j2));
}
int main(){
    int m,n;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i]);
        s[i]+=s[i-1];
    }
    for(int k=1;k<=m;k++){
        l=1,r=1;Q[1]=0;
        for(int i=1;i<=n;i++){
            while(l<r&&slop(Q[l],Q[l+1],k)<=s[i])l++;
            int j=Q[l];
            f[i][k]=f[j][k-1]+(s[i]-s[j])*s[j];
            ans[i][k]=j;
            while(l<r&&slop(Q[r-1],Q[r],k)>=slop(Q[r],i,k))r--;
            Q[++r]=i;
        }
    }
    printf("%lld",f[n][m]);
    puts("");
    while(m){
        printf("%d ",ans[n][m]);
        n=ans[n][m],m--;
    }
    return 0;
}

而维护上凸壳就WA两个点?

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5,M=255;
LL s[N],f[N][M];
int l,r,Q[N],ans[N][M];
long double X(int j){return s[j];}
long double Y(int j,int k){return (f[j][k-1]-s[j]*s[j]);}
long double slop(int j1,int j2,int k){
    if(X(j1)==X(j2))return -1e18;
    return (Y(j2,k)-Y(j1,k))/(X(j2)-X(j1));
}
int main(){
    int m,n;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i]);
        s[i]+=s[i-1];
    }
    for(int k=1;k<=m;k++){
        l=1,r=1;Q[1]=0;
        for(int i=1;i<=n;i++){
            while(l<r&&slop(Q[l],Q[l+1],k)>=(-s[i]))l++;
            int j=Q[l];
            f[i][k]=f[j][k-1]+(s[i]-s[j])*s[j];
            ans[i][k]=j;
            while(l<r&&slop(Q[r-1],Q[r],k)<=slop(Q[r],i,k))r--;
            Q[++r]=i;
        }
    }
    printf("%lld",f[n][m]);
    puts("");
    while(m){
        printf("%d ",ans[n][m]);
        n=ans[n][m],m--;
    }
    return 0;
}
2023/8/18 08:15
加载中...