题面传送门
看到这个不难想到dp
首先有一个基本结论:如果两个点\((x_i,y_i),(x_j,y_j)\)满足\(x_i\geq x_j\)且\(y_i\leq y_j\)那么\((x_i,y_i)\)是没有用的。
所以我们可以得到一系列有用的点,满足\(y_i\geq y_{i-1}\)
所以不难想到\(O(n^2k)\)的dp,设\(f_{i,j}\)为选了\(i\)个区间,到了第\(j\)个点的答案。
设\(W_i\)为\((x_i,y_i)\)与\((x_{i-1},y_{i-1})\)重叠的部分,那么有\(dp_{i,j}=\min\limits_{h\leq i}{dp_{i-1,h}-W_j+(Y_j-X_h+1)^2}\)
发现有一个平方项,不难想到用斜率优化,就可以优化成\(O(nk)\),60pts
恰好\(k\)个很像wqs二分的形式。然后这个又是个凸函数,直接上wqs二分就好了,时间复杂度\(O(nlogm)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 100000
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,k,Ne,La,Maxn,L[N+5],R[N+5],M,Q[N+5],T,g[N+5],H;ll dp[N+5],W[N+5],l,r,mid;
struct Edge{int l,r;}S[N+5];I bool cmp(Edge x,Edge y){return x.l^y.l?x.l<y.l:x.r>y.r;}
I db slope(int j,int h){return ((dp[h-1]-W[h]+1ll*(L[h]-1)*(L[h]-1))-(dp[j-1]-W[j]+1ll*(L[j]-1)*(L[j]-1)))*1.0/(L[h]-L[j]);}
I int check(){
RI i;H=1;T=0;Me(dp,0x3f);dp[0]=0;g[0]=0;for(i=1;i<=M;i++){
while(H<T&&slope(Q[T-1],Q[T])>slope(Q[T],i)) T--;Q[++T]=i;while(H<T&&slope(Q[H],Q[H+1])<2*R[i]) H++;
dp[i]=dp[Q[H]-1]-W[Q[H]]+1ll*(R[i]-L[Q[H]]+1)*(R[i]-L[Q[H]]+1)+mid;g[i]=g[Q[H]-1]+1;
}return g[M]>k;
}
int main(){
freopen("1.in","r",stdin);
RI i,j,h;scanf("%d%d%d",&n,&m,&k);l=-1;r=1ll*m*m+1;for(i=1;i<=n;i++) scanf("%d%d",&S[i].l,&S[i].r),S[i].l>S[i].r&&(swap(S[i].l,S[i].r),0);sort(S+1,S+n+1,cmp);
Maxn=-1e9;for(i=1;i<=n;i++) S[i].r>Maxn&&(L[++M]=S[i].l,R[M]=S[i].r,Maxn=S[i].r);for(i=2;i<=M;i++) W[i]=1ll*max(0,R[i-1]-L[i]+1)*max(0,R[i-1]-L[i]+1);
k=min(k,M);while(l+1<r) mid=l+r>>1,(check()?l:r)=mid;mid=r;check();printf("%lld\n",dp[M]-k*mid);
}