题意
给定一个区间集s,含n个开区间,对于这个区间集,定义最长k可重区间集为s的一个子集s',s'满足:
对于数轴上任意一个点,最多被区间s'内的区间覆盖k次。
定义对于一个区间集,它的长度为子集内所有区间的长度总和。
最长k可重区间集为所有s'里最长的长度。
分析
简单来说就是考虑找k个不重叠的区间集使得长度最长,每个区间最多被取一次。
第一步就没想到
然后来考虑这个东西怎么寻找。
可以简单的发现,如果要不重叠,那么选定一段区间之后这个区间覆盖的所有区间都不能取,但是之后的区间又都可以取。
然后就会变成类似DP一样的东西。但是这个时候发现写不动啊。因为每一个区间最多被使用一次。
考虑到这个限制,来想一想网络流吧。
然后建图也很明朗了...
首先离散。假设最后剩下来的点一共有tot个。
建立源点s和汇点t,s连一条到1节点流量为k费用为0的边,tot连一条到t节点流量为k(其实大于等于k都行)费用为0的边。
然后对于每个点i,如果i+1存在的话,那么连一条i到i+1流量为inf(其实大于等于k都行)费用为0的边。
然后对于区间集内任意一对(l,r)连一条离散后,l到r流量为1(只能使用一次),费用为len(l,r)的边。
然后跑一次最大费用最大流就好了。
code
#include<bits/stdc++.h>
#define M 1005
#define inf 1000000000
using namespace std;
void read(int &x){
x=0; char c=getchar();
for (;c<48;c=getchar());
for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
struct ed{
int x,cap,cost,nx;
}e[M*20];
int nx[M],ecnt;
void add(int x,int y,int cap,int cost){
// printf("%d %d %d %d\n",x,y,cap,cost);
e[ecnt]=(ed){y,cap,cost,nx[x]};
nx[x]=ecnt++;
e[ecnt]=(ed){x,0,-cost,nx[y]};
nx[y]=ecnt++;
}
struct EK_EK{
int Q[M],dis[M],nxt[M],s,t,l,r,Flow,Cost;
bool vis[M];
bool spfa(int x){
// printf("s=%d t=%d\n",s,t);
for (int i=s;i<=t;i++)dis[i]=-inf;
dis[x]=0;
l=r=0;
Q[r++]=x;
for (;l!=r;){
x=Q[l++]; l%=M;
vis[x]=0;
for (int i=nx[x];~i;i=e[i].nx)if (e[i].cap>0&&e[i].cost+dis[x]>dis[e[i].x]){
dis[e[i].x]=dis[x]+e[i].cost; nxt[e[i].x]=i;
if (!vis[e[i].x]){
Q[r++]=e[i].x; vis[e[i].x]=1; r%=M;
}
}
}
return dis[t]>-inf;
}
int dfs(int x,int f){
if (x==s){
Cost+=f*dis[t];
return f;
}
int res=dfs(e[nxt[x]^1].x,min(f,e[nxt[x]].cap));
e[nxt[x]].cap-=res; e[nxt[x]^1].cap+=res;
return res;
}
void solve(int ss,int tt){
s=ss; t=tt;
for (;spfa(s);){
Flow+=dfs(t,inf);
}
}
}EK;
int a[M],l[M],r[M];
int ch(int l,int r,int x){
for (;;){
int mid=(l+r)>>1;
if (a[mid]==x)return mid;
if (a[mid]<x)l=mid+1;else r=mid-1;
}
}
int main(){
// freopen("LOJ6014.in","r",stdin);
int n,k;
read(n); read(k);
for (int i=1;i<=n;i++){
read(l[i]); read(r[i]);
if (l[i]>r[i])swap(l[i],r[i]);
a[i]=l[i]; a[i+n]=r[i];
}
sort(a+1,a+n+n+1);
memset(nx,-1,sizeof(nx));
int tot=unique(a+1,a+n+n+1)-a-1;
int s,t;
s=0; t=tot+1;
add(s,1,k,0); //add(tot,t,k,0);
for (int i=1;i<=tot;i++)add(i,i+1,inf,0);
for (int i=1;i<=n;i++){
int len=r[i]-l[i];
l[i]=ch(1,tot,l[i]); r[i]=ch(1,tot,r[i]);
// printf("%d %d\n",l[i],r[i]);
add(l[i],r[i],1,len);
}
EK.solve(s,t);
printf("%d\n",EK.Cost);
return 0;
}