题意:
给出
l1,r1,l2,r2,n,k
初始a集合表示n个区间
[l1,r1]
b集合表示n个区间
[l2,r2]
你一次操作能把一个区间
[x,y]扩大成
[x−1,y]或
[x,y+1]
问至少多少次操作,使得
∑i=1i=nbi&ai
其中
ai&bi在这里指两个区间的相交线段长度
Ⅰ.分析问题
很明显可以分成
[l1,r1]和
[l2,r2]是否相交的情况
Ⅰ.相交时
初始每个区间有len=min(r1,r2)−max(l1,l2)的线段长度相交
所以初始状态有slen=len∗n长度
拿k−=slen,若k为负数则一次都不用操作
否则继续看
我们可以只扩大a集合区间的右端点就能填充w
我们可以只扩大b集合区间的左端点就能填充q
这样的操作一直持续q+w次可以一次操作增加1长度
也就最多有n∗(q+w)次1换1的机会
用完之后,a区间和b区间重合,就只有2换1的机会(a区间往左扩大,b区间也往左扩大)
简单计算一下即可
Ⅱ.不相交时
首先要使区间相交,代价是co=min(r1−l2,r2−l1)
假设现在必须使x个区间相交最划算,那么有x∗co的操作用来相交
然后你有[max(r1,r2)−min(l1,l2)]∗n的机会1换1(1次操作增加1)
然后你有无限次机会2换1
至于x怎么最优,for大力枚举即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l1,r1,l2,r2,t,k;
int main()
{
cin >> t;
while( t-- )
{
ll ans=1e18;
cin >> n >> k;
cin >> l1 >> r1 >> l2 >> r2;
if( r1<l2||l1>r2 )//一开始不相交的情况
{
ll temp=0,len=max(r1,r2)-min(l1,l2);
if( r1<=l2) temp=l2-r1;
else if( l1>=r2 ) temp=l1-r2;//temp表示需要操作temp次使线段相交
for(ll i=1;i<=n;i++)//枚举使几个线段相交
{
ll sumn=len*i;//有sumn次1换1的机会
if( sumn>=k ) ans=min(ans,temp*i+k);
else ans=min(ans,len*i+temp*i+(k-sumn)*2);
}
cout << ans << endl;
}
else
{
ll jiao=min(r1,r2)-max(l1,l2);//初始相交长度
ll len=max(r1,r2)-min(l1,l2)-jiao;//有len次1换1的机会
k-=jiao*n;
if( k<=0 ) cout << 0 << endl;
else if( len*n>=k ) cout << k << "\n";
else
cout << len*n+(k-len*n)*2 << "\n";
}
}
}