[补题] Codeforces Round 892 (Div. 2)
Codeforces Round 892 (Div. 2)
感觉被诈骗了ww
A
Translate & Description
你有一个\(a\)数组,你可以将\(a\)数组的每一个数放到\(b\)数组或者\(c\)数组中。构造完后你需要确保\(\forall b_i\)%\(\forall c_j \ne 0(i\in [1,n],j\in[1,m])\) (我们规定\(n\)为\(a\)数组的大小,\(m\)为\(b\)数组的大小。数组下标均从\(1\)开始)。
输出共三行,第一行两个整数,分别为\(n\)和\(m\),显然你需要保证\(n+m=size(a)\)(\(size(a)\)为初始\(a\)数组的大小)
第二行\(n\)个整数,即你构造的\(b\)数组
第三行\(m\)个整数,即你构造的\(c\)数组
本题开启spj,你的构造只要符合题意都判定为正确而无需和stdoutput一致。
%我不会打latex就直接打了ww
Analysis
一道非常CF的构(zha)造(pian)题
我们需要保证我们构造出来的\(b,c\)数组中\(\forall c_i\)不是\(\forall b_i\)的除数。也就是不能整除。
我们是不是只要确保\(\forall c_i > \forall b_i\)就可以啦?
由此,我们可以直接判断出无解情况:当且仅有\(a\)数组所有数都相同时,无解。
反证:假设\(a\)数组中并不是所有数都不相同,则\(a\)数组中存在最大值。我们可以把不等于数组最大值的数字放到\(b\)数组中,反之等于最大值的数字放到\(c\)数组中,这样显然可以确保\(\forall c_i > \forall b_i\)。构造符合题意。
上述反证即为具体操作过程。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 20010;
int T;
int n;
int a[N];
int main()
{
scanf("%d",&T);
while(T--)
{
int pos = 0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
if(a[1] == a[n])
{
cout<<"-1"<<endl;
continue;
}
int cnt1 = 0;
for(int i=1;i<=n;i++)
{
if(a[i] != a[n])
{
// cout<<a[i]<<" ";
cnt1 ++;
}
else
{
pos = i;
break;
}
}
cout<<cnt1<<" "<<n-cnt1<<endl;
for(int i=1;i<=n;i++)
{
if(a[i] != a[n])
{
cout<<a[i]<<" ";
// cnt1 ++;
}
else
{
pos = i;
break;
}
}
cout<<endl;
for(int i=pos;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
}
}
B
Translate & Description
你有\(m\)个数组,你可以对每次数组进行一次操作,当然也可以不操作,操作如下:
- 将该数组的一个数移动到另一个数组中
注意,你可以对每个数组都进行一次这样的操作,而不是只进行一次操作(当时比赛理解错题意了qwq)
所有操作完成后,求每个数组的最小值和最大。形式化地,求\(max( \sum_{i=1}^n \min_{j=1}^{m_i} a_{i,j} )\)
Analysis
不妨考虑什么数字会对答案产生贡献。
首先,也是最容易想到的是,\(m\)个数组中所有数的最小值一定会产生贡献,因为无论怎么移动她都是一个数组的最小值。
接下来考虑移动。
首先一个结论,能够对答案产生贡献的只有每个数组的最小值和次小值。
简单理解一下:每个数组要么移动,要么不移动。如果移动只有移动最小值才对该数组的最小值产生贡献,那么此时产生贡献的是次小值。如果不移动那么产生贡献的是最小值。因为一个数组最多只能进行一次操作。所以最优策略是移动一个数组的最小值,这样才能对该数组的MINN产生正贡献,而这样的操作使得一个数组的次小值对答案产生贡献。
而如果我们把一个数组中不是最小值的数移动到另一个数组,不仅不会改变当前数组的最小值,还不会改变另一个数组的最小值,具体证明如下:
定义移动过来的数是\(x\),原来该数组的minn 为\(y\)
- 若$ x > y $则不会产生任何贡献
- 若\(x < y\) 则会产生负贡献
- 若\(x = y\) 则显然不会有贡献
由此看来我们如果移动一个数组中不是MINN的数,要么没有贡献,要么产生负贡献,我们显然不会去这么做。
而我们想要利益最大化可以将每个数组都移动。
如何移动呢?
前面提到\(m\)个数组中所有数的最小值一定会产生贡献,我们可以把她单独放到一个数组中,再把所有数组的最小值放到这个数组中,这样对答案产生贡献的就是所有数字的最小值+除了所有数字最小值所在数组其他所有数组的次小值。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 20010;
int T;
int n;
int a[N];
int main()
{
scanf("%d",&T);
while(T--)
{
int pos = 0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
if(a[1] == a[n])
{
cout<<"-1"<<endl;
continue;
}
int cnt1 = 0;
for(int i=1;i<=n;i++)
{
if(a[i] != a[n])
{
// cout<<a[i]<<" ";
cnt1 ++;
}
else
{
pos = i;
break;
}
}
cout<<cnt1<<" "<<n-cnt1<<endl;
for(int i=1;i<=n;i++)
{
if(a[i] != a[n])
{
cout<<a[i]<<" ";
// cnt1 ++;
}
else
{
pos = i;
break;
}
}
cout<<endl;
for(int i=pos;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
}
}
UPD:2023/8/15
熬不住了改天再更
本文作者:SXqwq,转载请注明原文链接:https://www.cnblogs.com/SXqwq/p/17630137.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!