Codeforces Round 860 (Div. 2) A-D题解

发布时间 2023-03-27 13:33:21作者: HikariFears

比赛地址

A.Showstopper

题意:给两个数组a和b,可以进行任意次操作:交换a[i]和b[i],问能否使得a[n]和b[n]分别是数组a和b的最大值

Solution

假设a[n]和b[n]固定,对于每一个i,a[i]和b[i]只能选其中之一,并且必须选择比a[n]或者b[n]小的,如果只能选同一个,或者a[i]与b[i]均比a[n]或b[n]大,那么肯定不符合

void solve()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++)
	{
		aa[i][0]=aa[i][1]=bb[i][0]=bb[i][1]=0;
	}
	for(int i=1;i<=n;i++)
	{
		if(a[i]<=a[n])aa[i][0]=1;
		if(b[i]<=a[n])aa[i][1]=1;
		if(a[i]<=b[n])bb[i][0]=1;
		if(b[i]<=b[n])bb[i][1]=1;
	}
	for(int i=1;i<=n;i++)
	{
		if(aa[i][0]==1&&aa[i][1]==0&&bb[i][0]==1&&bb[i][1]==0)
		{
			cout<<"No\n";
			return;
		}
		if(aa[i][0]==0&&aa[i][1]==1&&bb[i][0]==0&&bb[i][1]==1)
		{
			cout<<"No\n";
			return;
		}
		if((aa[i][0]==0&&aa[i][1]==0)||(bb[i][0]==0&&bb[i][1]==0))
		{
			cout<<"No\n";
			return;
		}
	}
	cout<<"Yes\n";
}

B.Three Sevens

题意:有一个活动开展m天,对于第i天,有ni人参加,并且给出这ni个人的数字代号,对于每一天,都会有一个胜者,并且这个胜者在接下来的几天内都不能参加活动,给出一种可能的答案,或者输出不能

Solution

直接倒着遍历就行了,用set存一下已经出现的

void solve()
{
	for(int i=1;i<=50000;i++)v[i].clear();
	int e;cin>>e;
	set<int>st;
	for(int i=1;i<=e;i++)
	{
		int n;cin>>n;
		for(int j=1;j<=n;j++)
		{
			int x;cin>>x;
			v[i].push_back(x);
		}
	}
	for(int i=e;i>=1;i--)
	{
		int flag=0;
		for(auto it:v[i])
		{
			if(st.count(it))continue;
			if(!flag)
			{
				flag=1;
				ans[i]=it;
			}
			st.insert(it);
		}
		if(!flag)
		{
			cout<<"-1\n";
			return;
		}
	}
	for(int i=1;i<=e;i++)cout<<ans[i]<<" ";
	cout<<"\n";
}

C.Candy Store

题意:给出n种糖果的个数和单价,不能改变糖果的顺序,将糖果分成几袋,不能有剩余,使得每袋都有一个单价,相同单价且相邻的糖果使用同一个标签,问如何分使得需要用的标签数量最少

Solution

两个不同单价的糖果如果要变成相同单价,则他们需要变成最小公倍数,然后根据最小公倍数去从个数里面分因数,如果个数%(最小公倍数/单价)=0,说明可以变成相同单价,反之则不行,然后维护一下已经相同单价的糖果个数在除以(最小公倍数/单价)以后的最大公约数即可。

void solve()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++)cin>>e[i].a>>e[i].b;
	int ans=1;
	set<int>st;
	node p;
	p.a=-1,p.b=-1;
	for(int i=2;i<=n;i++)
	{
		if(p.a==-1) //如果前面只有一种糖果
		{
			int x=lcm(e[i-1].b,e[i].b);
			int a1=x/e[i-1].b;
			int a2=x/e[i].b;
			if(e[i-1].a%a1!=0||e[i].a%a2!=0)ans++;
			else
			{
				int x1=e[i-1].a/a1;
				int x2=e[i].a/a2;
				p.a=gcd(x1,x2),p.b=x;
			}
		}else //如果前面有多个相同单价的
		{
			int x=lcm(p.b,e[i].b);
			int a1=x/p.b;
			int a2=x/e[i].b;
			if(p.a%a1!=0||e[i].a%a2!=0)
			{
				ans++;
				p.a=-1,p.b=-1;
			}
			else
			{
				int x1=p.a/a1;
				int x2=e[i].a/a2;
				p.a=gcd(x1,x2),p.b=x;
			}
		}
	}
	cout<<ans<<"\n";
}

D.Shocking Arrangement

题意:给出长度为n的并且和为0的数组,将其重新排序,使得对于任意一个子区间的和都小于数组中的最大值-数组中的最小值

Solution

贪心,将数组按升序排序,然后令l=1,r=n,令up=max-min,每次填入前判断目前的总和再加上a[r]后是否会大于等于up,如果大于等于的话就填入a[l],并令l++,反之填入a[r],令r--

void solve()
{
    int n;
    cin >> n;
    int maxx=0,minn=1e18;
    for(int i=1; i<=n; i++)cin >> a[i];
    sort(a+1,a+1+n);
    int l=1,r=n;
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        if(i==1)
        {
            ans[i]=a[r--];
        } else
        {
            if(a[r] + sum >= a[n] - a[1])
            {
                ans[i] = a[l++];
            } else ans[i] = a[r--];
 
        }
        sum + = ans[i];
        if(sum >= a[n]-a[1])
        {
            cout << "No" << endl;
            return;
        }
    }
    cout << "Yes" << endl;
    for(int i=1; i<n+1; i++) cout << ans[i] << ' ';
    cout<< endl;
}