新人求助,WA一个点很难受
  • 板块P4983 忘情
  • 楼主SegmentTree
  • 当前回复4
  • 已保存回复4
  • 发布时间2020/7/20 18:34
  • 上次更新2023/11/6 22:44:43
查看原帖
新人求助,WA一个点很难受
118308
SegmentTree楼主2020/7/20 18:34
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long double db;
typedef long long ll;
const int N=210000;
const ll inf=1e17;
int n,m;
ll a[N],s[N];
int q[N],l,r;
ll c[N],f[N];
db x(int i) {return 1.0*s[i];}
db y(int i) {return 1.0*f[i]+s[i]*s[i];}
db k(int i) {return 2.0*(s[i]+1);}
db slope(int i,int j)
{
  return (y(i)-y(j))/(x(i)-x(j));
}
int check(ll mid)
{
  f[0]=c[0]=0;
  q[l=r=1]=0;
  for(int i=1;i<=n;i++)
  {
    while(l<r&&slope(q[l],q[l+1])<k(i)) l++;
    int j=q[l];
    f[i]=f[j]+(s[i]-s[j]+1)*(s[i]-s[j]+1)+mid;
    c[i]=c[j]+1;
    while(l<r&&slope(q[r],q[r-1])>slope(q[r],i)) r--;
    q[++r]=i;
  }
  return c[n];
}
signed main()
{
  scanf("%lld%lld",&n,&m);
  for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
  for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
  ll l=0,r=inf,best=-1;
  while(l<=r)
  {
    ll mid=(l+r)/2;
    if(check(mid)<=m) best=mid,r=mid-1;
    else l=mid+1;
  }
  check(best);
  printf("%lld\n",f[n]-best*c[n]);
  return 0;
}
2020/7/20 18:34
加载中...