题意: 分别给出 n 个区间 [ a l 1 , a r 1 ] , [ a l 2 , a r 2 ] , … , [ a l n , a r n ] [al_1, ar_1], [al_2, ar_2], \dots, [al_n, ar_n] [al1,ar1],[al2,ar2],…,[aln,arn] 其初始值均为 [ l 1 , r 1 ] [l_1,r_1] [l1,r1] 和 [ b l 1 , b r 1 ] , [ b l 2 , b r 2 ] , … , [ b l n , b r n ] [bl_1, br_1], [bl_2, br_2], \dots, [bl_n, br_n] [bl1,br1],[bl2,br2],…,[bln,brn] 其初始值均为 [ l 2 , r 2 ] [l_2,r_2] [l2,r2]。定义: ( [ a l i , a r i ] , [ b l i , b r i ] ) ([al_i, ar_i], [bl_i, br_i]) ([ali,ari],[bli,bri]) 为两个区间的交集长度,求这 n 对区间的交集长度之和大于等于 k 所需要的最少操作次数。 每次操作可以延长区间一个单位。
思路: 其实就是分类讨论两个区间的关系:
1、两区间相交,设相交长度为 len ,则初始值为 len * n ,之后往左边或右边没有相交的区间延长端点时均为1换1的代价,之后再延长既是2换1的代价。
2、同理,先把区间延长至相交,然后与之不同的是我们也要枚举延长的区间个数,同时计算代价,然后取最小的代价即可。(因为每多延长一对区间至相交时所花费代价不知是否值得)
Code:
#include
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long LL;
int main()
{
IO;
int T; cin>>T;
while(T--){
LL n,k,l1,r1,l2,r2;
cin>>n>>k>>l1>>r1>>l2>>r2;
if(r1<l2||r2<l1){ //不相交
LL s = min(abs(l2-r1),abs(l1-r2)); //间隔长度
LL len = max(r1,r2)-min(l1,l2); //连接两个区间后的总长度
LL ans = 1e18;
for(int i=1;i<=n;i++){ //枚举需要相交的区间数,取最值
if(len*i>=k) ans = min(ans,s*i+k);
else ans = min(ans,s*i+len*i+(k-len*i)*2);
}
cout<<ans<<"\n";
}else{ //相交
LL t = min(r1,r2)-max(l1,l2); //相交长度
k-=t*n;
if(k<=0) cout<<"0\n";
else {
t = abs(r1-r2)+abs(l1-l2); //1换1 的长度
if(k<=t*n) cout<<k<<"\n";
else cout<<t*n+(k-t*n)*2<<"\n"; //剩下的2换1
}
}
}
return 0;
}