后院总共有n片草坪,第i片草坪投影到数轴上,是一段l[i]到r[i]的闭区间,保证l[i]+r[i]是偶数,l[i]<=r[i]。
Sullivan可以在整点上放0v0来把草吃掉(于是0v0变成了0π0)。如果第i片草坪覆盖了x点上的0π0(l[i]<=x<=r[i]),那么这只0π0就可以吃掉这片草坪里的草。每一片草坪的草需要且只能被一只0π0吃掉。如果一片草坪覆盖了多只0π0,Sullivan可以选择任意一只去吃草。
但是,0π0吃草是有代价的,对于第i片草坪,假如吃草的0π0位于x点上,代价为abs((x-l[i])-(r[i]-x)),即0π0到草坪两端距离之差。
现在,Sullivan想知道:
1.最少需要放几只0v0?
2.在放最少只数的0v0情况下,代价最小是多少?
如果只要求至少放多少个,贪心即可,每次找到最左的一个l,放下去。
怎么求方案呢,
考虑不用贪心,用DP,
设 fi 表示在i放,
O(n2) 的转移显然,只要合法均可以转移,
考虑怎么求最小的代价,
原式: |li+ri−2x|
因为数据保证 li+ri 为偶数,设 ai=(li+ri)/2
所以: 2|ai−x|
因为要保证有解,所以求代价不用考虑是否合法,最小的情况一定合法,
如果从j转移到i,那么代价怎么计算:
mid=(i+j)/2 ,那么对于 ak(j<ak<i) ,在mid左边的就去j,右边的就去i,
计算答案就记录俩前缀和即可,
这样的复杂度是 O(n2) 的(其实可以过2333)
进一步考虑发现,这个是具有决策单调性的,
那么就可以优化到O(n)了,
// fi 表示代价, gi 表示最少放多少个
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define min(q,w) ((q)>(w)?(w):(q))
#define JS(i,j,mid) (f[j]+(b[mid][1]-b[j][1]-(b[mid][0]-b[j][0])*(j))+(-b[i][1]+b[mid][1]+(b[i][0]-b[mid][0])*(i)))
using namespace std;
typedef long long LL;
const int N=300500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,mxl,ans;
LL ans1;
struct qqww
{
int l,r;
}a[N];
int b[N][2];
LL f[N];
int g[N];
bool PX(qqww q,qqww w){return q.rint main()
{
int w,_,lst;
read(n),read(_);
fo(i,1,n)read(a[i].l),read(a[i].r);
sort(a+1,a+1+n,PX);
fo(i,1,n)b[(a[i].l+a[i].r)>>1][0]++;
fo(i,1,a[n].r)b[i][1]=b[i-1][1]+b[i][0]*i,b[i][0]+=b[i-1][0];
mxl=w=lst=0;
fo(i,1,a[n].r)
{
f[i]=1e11;g[i]=1e9;
for(;w<=n&&a[w].rif(lst1)if(g[i]>=g[j]+1)
{
int mid=(j+i)>>1;
if(g[i]>g[j]+1)g[i]=g[j]+1,f[i]=1e11,lst=j;
LL t=JS(i,j,mid);
f[i]=min(f[i],t);
}
else break;//决策单调优化
}
for(;w<=n;w++)mxl=max(mxl,a[w].l);
ans=1e9;
fo(i,mxl,a[n].r)ans=min(ans,g[i]);
printf("%d\n",ans);
ans1=1e11;
fo(i,mxl,a[n].r)if(ans==g[i])ans1=min(ans1,f[i]+b[a[n].r][1]-b[i][1]-(b[a[n].r][0]-b[i][0])*i);
if(_)printf("%lld\n",2LL*ans1);
return 0;
}