CF每日5题Day5(1400)
每日打卡。感觉自己过题效率很低,浪费了很多时间。
1- 1266C 构造
水题
- b数组是r+c个gcd,各个不重样,就分配b数组为 { 1 , 2 , 3 , . . . , r + c } \{1,2,3,...,r+c\} {1,2,3,...,r+c}
- 注意特判 r=1或c=1的时候,a数组每一个数自己就是本行/列的gcd
- r=1且c=1的时候 行和列gcd一定相等,都等于a数组的这个数,所以不存在b
const int N=510;
int a[N][N];
void solve(){
int r,c;
cin>>r>>c;
if(r==1&&c==1)return cout<<0<<endl,void();
if(r==1){
a[1][1]=2;
forr(i,2,c){
a[1][i]=a[1][i-1]+1;
}
}else if(c==1){
a[1][1]=2;
forr(i,2,r){
a[i][1]=a[i-1][1]+1;
}
}else{
reforr(i,1,c){
a[1][i]=i+r;
}
forr(i,2,r){
forr(j,1,c){
a[i][j]=a[1][j]*i;
}
}
}
forr(i,1,r){
forr(j,1,c)cout<<a[i][j]<<' ';cout<<endl;
}
}
2- 534B 思维 贪心
一下子没想出思路来 想出来发现是水题
- 路程最长,需要速度能多大就多大,所以在走的过程中尽量+d
- 从前往后、从后往前分别找能达到的速度,取该时刻两速度较小的那个。
void solve(){
int v1,v2,t,d;
cin>>v1>>v2>>t>>d;
vector<int>a(t+1);
a[1]=v1;
forr(i,2,t)a[i]=a[i-1]+d;
int v=v2+d,l=v2;
reforr(i,1,t-1){
int vn=min(a[i],v);
// cout<<vn<<endl;
l+=vn;
v+=d;
}
cout<<l<<endl;
}
3- 1009B 找规律
模拟必超时,所以要找规律
通过仔细地读题我们可以知道,0 和 1 可以交换,1 和 2 可以交换,而 0 和 2 不可以交换。
也就是说 1 可以交换到整个字符串中任何一个位置。
那么,我们可以把所有的 1 取出,只剩下由 0 和 2 组成的字符串。
引用自洛谷
void solve(){
string s,ans;
int ones=0;
cin>>s;
int l=s.size();
forr(i,0,l-1){
if(s[i]=='1')ones++;
else ans+=s[i];
}
if(ones==0)return cout<<ans<<endl,void();
int al=ans.size(),pos=al;
forr(i,0,al-1){
if(ans[i]=='2'){
pos=i;break;
}
}
forr(i,0,al-1){
if(i==pos){
while (ones-->0)cout<<1;
}
cout<<ans[i];
}
while ((ones--)>0)cout<<1;
}
4- 1896C 贪心 排序
- 题意是改变 b b b的顺序 能有x个 a i > b i a_i>b_i ai>bi
- 配对
- 用 a a a中前x大的数, b b b后x小的数,去凑这x个 a i > b i a_i>b_i ai>bi
- 其他的n-x个数一定 a i < = b i a_i<=b_i ai<=bi
- 不满足上两条就不存在
- 较大的配较大的 较小的配较小的 要不不够
const int N=2e5+10;
struct num{
int id,val;
}a[N];
int b[N],ans[N];
bool decrease(num x,num y){return x.val>y.val;}
bool rise(num x,num y){return x.val<y.val;}
void solve(){
int n,x;
cin>>n>>x;
forr(i,1,n){cin>>a[i].val;a[i].id=i;}
forr(i,1,n){cin>>b[i];}
sort(a+1,a+n+1,rise);
sort(b+1,b+n+1);
int ida=n-x+1,idb=1;
//先凑a中最大的x个数 看能不能凑出x个
//较小的跟较小的配
forr(i,1,x){
if(a[ida].val<=b[idb])return cout<<"no"<<endl,void();
ans[a[ida].id]=b[idb],ida++,idb++;//配对
}
ida=1;
forr(i,1,n-x){
if(a[ida].val>b[idb])return cout<<"no"<<endl,void();
ans[a[ida].id]=b[idb],ida++,idb++;
}
cout<<"yes"<<endl;
forr(i,1,n){
cout<<ans[i]<<' ';
}cout<<endl;
}
5- 1764C 思维 贪心
- 题目要求每个点 a i a_i ai不能同时连比它大的和比它小的值,所以这个点要么都连严格比它大的,要么都连严格比它小的
- 一部分点要连比它大的,另一部分就连比它小的
- 所以把一组数分成较大的和较小的部分,两部分相连
- 对于相同的数,把放进同一个部分
- 但是如果数组中数都相同,就两两之间连一条线,这是最优
void solve(){
int n;cin>>n;
vector<int>a(n);
forr(i,1,n){
cin>>a[i-1];
}
sort(a.begin(),a.end());
int ans=-1,now=0;
forr(i,0,n-2){
if(a[i]==a[i+1])continue;
now=a[i];
ans=max(ans,(i+1)*(n-i-1));
}
if(ans==-1)ans=n/2;
cout<<ans<<endl;
}