cf #768 Div.2
文章目录
A. Min Max Swap
- 题意
两个数组a,b,对于同一下标i可以交换a[i],b[i]的值,求max(a)*max(b)最小值
-
题解
题目就是要通过某些操作让两个数组中的最值m1*m2乘积最小,首先,所有数的最大值一定是一个数组的最大值死,即m1已经固定,所以需要通过操作使得另一个数组中的最大值m2最小,我们让m1在a中,那么只需把所有a[i]<b[i]的下标都交换,就可以在最大可能下使得b中m2最小,即使得答案最小。
-
代码
#include <iostream>
using namespace std;
const int N=110;
int n;
int a[N],b[N];
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++)
if(a[i]<b[i]) swap(a[i],b[i]);//把最大值组置为a数组
int m1=0,m2=0;
for(int i=0;i<n;i++) {//找m1,m2
m1=max(m1,a[i]);
m2=max(m2,b[i]);
}
cout<<m1*m2<<'\n';
}
return 0;
}
B. Fun with Even Subarrays
-
题意
给定一个整数数组a下标从1开始,可以进行这样的操作:随便选l,k,把a[l,l+k)替换成a[l+k,l+k+k),问最少经过几次这样的操作可以让a中所有数都相等。
-
题解
由于题意是把前一个区间段替换成后一个区间段,为了能够尽可能少的次数变成一样的,那么就要求后一个区间段必须已经完全相等。所以从边界开始,最右端的最后一个完全相等的的区间把前一个区间替换,接着把这两个区间看成一整个区间,再把合成区间的前一个区间替换,如此继续直到达到最左端。
Eg:
原数组: 4 2 1 3(第一个区间长度为1,数值为3,被替换的数字为1)
替换后: 4 2 3 3(第二个区间长度为2,数值为33, 被替换的数字为42)
替换后: 3 3 3 3(第三个区间长度为4,数值为3333,成功操作 )
-
代码
#include <iostream>
using namespace std;
const int N=2e5+5;
int n;
int a[N];
int solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int cnt=0,len=1;//记录次数、已经相等的最大区间长度
for(int i=n;i>0;i--){//从后往前依次最大限度替换
if(a[n]==a[i-1] && i-1) len++;//如果和最后一个数相等则区间长度++
if(a[n]!=a[i-1] && i-1) {//不等则替换,注意不能越界
cnt++;//替换次数++
i-=len;i++;//下一区间的尾部的指针更新
len*=2;//长度增倍
}
}
return cnt;
}
int main() {
int T;
cin>>T;
while(T--)
cout<<solve()<<'\n';
return 0;
}
C. And Matching
-
题意
给定一个2的幂n[4,2^16],一个整数k[0,n),同时包含0~n-1这些数,把这些数两两a,b一组分为n/2组,输出使得以下式子成立的分组方式
∑ i n / 2 a i & b i = k \sum^{n/2}_{i}a_i\& b_i=k i∑n/2ai&bi=k -
题解
以数字8为例
由以上规律可以得到一个一定可以构造出符合式子的分组:其他组别全部取为0,剩下0,n-1,k,Ck(表示与k做&为0的数)四个数,分成(0,Ck)=0,(n-1,k)=k,这样所有的和为k。当然这是在k<n-1的情况下才能剩下这四个数。因此分类讨论:
k<n-1 :按如上方法构造即可
k=n-1 :也有构造方法,其他组全取0,剩下0,1,2,n-3,n-2,n-1用来构成k
(n-1)&(n-2)=(n-2) , (n-3)&1=1 , 0&2=0 —>n-1=k
当然,当n=4时没办法给出6个数,所以不能构造成功
- 代码
#include <iostream>
using namespace std;
const int N=1e6+5;
int T,n,k,a[N];
int main() {
cin>>T;
while(T--){
cin>>n>>k;
for(int i=0;i<n;i++) a[i]=i;
if(k!=n-1) swap(a[0],a[k]);//第一类构造
else swap(a[0],a[n-2]),swap(a[n-2],a[n-3]);//第二类构造
if(n==4 && k==3) cout<<-1<<'\n';//如果n=4&&k=n-1那么没有答案
else {//输出分组
for(int i=0;i<n/2;i++) cout<<a[i]<<" "<<a[n-i-1]<<'\n';
}
}
return 0;
}