D - Segment Intersections *
题意: 分别给出 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<bits/stdc++.h>
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;
}