D. Segment Intersections(区间相交,模拟)

题意:

给出 l 1 , r 1 , l 2 , r 2 , n , k l1,r1,l2,r2,n,k l1,r1,l2,r2,n,k

初始a集合表示n个区间 [ l 1 , r 1 ] [l1,r1] [l1,r1]

b集合表示n个区间 [ l 2 , r 2 ] [l2,r2] [l2,r2]

你一次操作能把一个区间 [ x , y ] [x,y] [x,y]扩大成 [ x − 1 , y ] [x-1,y] [x1,y] [ x , y + 1 ] [x,y+1] [x,y+1]

问至少多少次操作,使得 ∑ i = 1 i = n b i & a i \sum_{i=1}^{i=n}b_i\&a_i i=1i=nbi&ai

其中 a i & b i a_i\&b_i ai&bi在这里指两个区间的相交线段长度

Ⅰ . 分 析 问 题 \color{Red}Ⅰ.分析问题 .

很明显可以分成 [ l 1 , r 1 ] [l1,r1] [l1,r1] [ l 2 , r 2 ] [l2,r2] [l2,r2]是否相交的情况

Ⅰ . 相 交 时 \color{Red}Ⅰ.相交时 .

初 始 每 个 区 间 有 l e n = m i n ( r 1 , r 2 ) − m a x ( l 1 , l 2 ) 的 线 段 长 度 相 交 初始每个区间有len=min(r1,r2)-max(l1,l2)的线段长度相交 len=min(r1,r2)max(l1,l2)线

所 以 初 始 状 态 有 s l e n = l e n ∗ n 长 度 所以初始状态有slen=len*n长度 slen=lenn

拿 k − = s l e n , 若 k 为 负 数 则 一 次 都 不 用 操 作 拿k-=slen,若k为负数则一次都不用操作 k=slen,k

否 则 继 续 看 否则继续看

我 们 可 以 只 扩 大 a 集 合 区 间 的 右 端 点 就 能 填 充 w 我们可以只扩大a集合区间的右端点就能填充w aw

我 们 可 以 只 扩 大 b 集 合 区 间 的 左 端 点 就 能 填 充 q 我们可以只扩大b集合区间的左端点就能填充q bq

这 样 的 操 作 一 直 持 续 q + w 次 可 以 一 次 操 作 增 加 1 长 度 这样的操作一直持续q+w次可以一次操作增加1长度 q+w1

也 就 最 多 有 n ∗ ( q + w ) 次 1 换 1 的 机 会 也就最多有n*(q+w)次1换1的机会 n(q+w)11

用 完 之 后 , a 区 间 和 b 区 间 重 合 , 就 只 有 2 换 1 的 机 会 ( a 区 间 往 左 扩 大 , b 区 间 也 往 左 扩 大 ) 用完之后,a区间和b区间重合,就只有2换1的机会(a区间往左扩大,b区间也往左扩大) ,ab,21(a,b)

简 单 计 算 一 下 即 可 简单计算一下即可


Ⅱ . 不 相 交 时 \color{Red}Ⅱ.不相交时 .

首 先 要 使 区 间 相 交 , 代 价 是 c o = m i n ( r 1 − l 2 , r 2 − l 1 ) 首先要使区间相交,代价是co=min(r1-l2,r2-l1) 使,co=min(r1l2,r2l1)

假 设 现 在 必 须 使 x 个 区 间 相 交 最 划 算 , 那 么 有 x ∗ c o 的 操 作 用 来 相 交 假设现在必须使x个区间相交最划算,那么有x*co的操作用来相交 使x,xco

然 后 你 有 [ m a x ( r 1 , r 2 ) − m i n ( l 1 , l 2 ) ] ∗ n 的 机 会 1 换 1 ( 1 次 操 作 增 加 1 ) 然后你有[max(r1,r2)-min(l1,l2)]*n的机会1换1(1次操作增加1) [max(r1,r2)min(l1,l2)]n11(11)

然 后 你 有 无 限 次 机 会 2 换 1 然后你有无限次机会2换1 21

至于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";	
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值