比较好想的建模题.
显然,如果选 $[l,r]$ 的话只要强制选 $[l,r-1]$ 与 $[l+1,r]$ 就行了.
然后 $m=0$ 的话直接在 $[i,i]$ 上扣掉编号大小就行.
如果 $m=1$,就套路的新建一个点,然后练一下限制的编号就行了.
code:
#include <bits/stdc++.h>
#define N 20006
#define M 103
#define I(s) freopen(s".in","r",stdin)
#define O(s) freopen(s".out","w",stdout)
#define setIO(s) I(s)
using namespace std;
const int inf=2000000001;
namespace net
{
struct Edge
{
int u,v;
int c;
Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
};
queue<int>q;
vector<Edge>edges;
vector<int>G[N];
int vv[N],vis[N],d[N],bo[N],s,t;
void add(int u,int v,int c)
{
edges.push_back(Edge(u,v,c));
edges.push_back(Edge(v,u,0));
int o=edges.size();
G[u].push_back(o-2);
G[v].push_back(o-1);
}
int dfs(int x,int cur)
{
if(x==t)
return cur;
int an=0,flow=0;
for(int i=vv[x];i<G[x].size();++i,++vv[x])
{
Edge e=edges[G[x][i]];
if(e.c>0&&d[e.v]==d[x]+1)
{
an=dfs(e.v,min(cur,e.c));
if(an)
{
cur-=an;
flow+=an;
edges[G[x][i]].c-=an;
edges[G[x][i]^1].c+=an;
if(!cur)
break;
}
}
}
return flow;
}
int bfs()
{
memset(vis,0,sizeof(vis));
d[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<G[u].size();++i)
{
if(edges[G[u][i]].c>0)
{
int v=edges[G[u][i]].v;
if(!vis[v])
{
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
}
return vis[t];
}
int maxflow()
{
int re=0;
while(bfs())
{
memset(vv,0,sizeof(vv));
re+=(int)dfs(s,inf);
}
return re;
}
};
int a[N],val[M][M],id[M][M];
vector<int>G[N];
int main()
{
// setIO("input");
int n,m,tim=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
G[a[i]].push_back(i);
}
for(int i=1;i<=n;++i)
{
for(int j=i;j<=n;++j)
scanf("%d",&val[i][j]),id[i][j]=++tim;
}
for(int i=1;i<=n;++i)
val[i][i]-=a[i];
int s=0,t=n*n+n+2,SUM=0;
net::s=s,net::t=t;
for(int i=1;i<=n;++i)
{
for(int j=i;j<=n;++j)
{
if(j>i)
{
net::add(id[i][j],id[i+1][j],inf);
net::add(id[i][j],id[i][j-1],inf);
}
if(val[i][j]>0)
{
SUM+=val[i][j];
net::add(s,id[i][j],val[i][j]);
}
else
{
net::add(id[i][j],t,-val[i][j]);
}
}
}
for(int i=0;i<=1000;++i)
{
if(G[i].size())
{
++tim;
net::add(tim,t,m*i*i);
for(int j=0;j<G[i].size();++j)
{
int y=G[i][j];
net::add(id[y][y],tim,inf);
}
}
}
printf("%d\n",SUM-net::maxflow());
return 0;
}