[BZOJ4709][JSOI2011]柠檬 决策单调性优化dp

题解:

单调栈优化

首先发现一个性质就是

如果当前i<j 转移f[i] 比 f[j]

我们要维护一个队列保证前一个超过后一个的时间单调不减

代码:

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define ll long long
#define rint register int
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
const int INF=1e9;
const int N=2e5+10;
int n;
ll f[N];
vector<int> g[N];
int s[N],a[N],cnt[N];
IL ll calc(int x,int y)
{
  return f[x-1]+1ll*a[x]*y*y;
}
IL int find(int x,int y)
{
  int h=max(s[x],s[y]),t=n;
  while(h<t)
  {
    int mid=(h+t)/2;
    if (calc(x,mid-s[x]+1)>=calc(y,mid-s[y]+1)) t=mid;
    else h=mid+1;
  }
  return(h);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>n;
  rep(i,1,n)
  {
    int x;
    cin>>x;
    a[i]=x; s[i]=++cnt[x];
    int k1=g[x].size();
    while (k1>=2&&find(g[x][k1-2],g[x][k1-1])<=find(g[x][k1-1],i))
      g[x].pop_back(),k1--;
    g[x].push_back(i); k1++;
    while (k1>=2&&find(g[x][k1-2],g[x][k1-1])<=s[i]) g[x].pop_back(),k1--;
    f[i]=calc(g[x][k1-1],s[i]-s[g[x][k1-1]]+1);
  }
  cout<<f[n];
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/yinwuxiao/p/9393755.html
今日推荐