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

题意:

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

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

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

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

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

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

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

很明显可以分成 [ l 1 , r 1 ] [l1,r1] [ l 2 , r 2 ] [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)的线段长度相交

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

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

否则继续看

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

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

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

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

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

简单计算一下即可


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

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

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

[ 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)

2 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";	
		}
	}
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107680453