比赛
比赛:Codeforces Round 900(Div.3)
做题时间:2023.11.13~2023.11.18
成绩:做过一道,补过四道
链接:Dashboard - Codeforces Round 900 (Div. 3) - Codeforces
一、How Much Does Daytona Cost?
题目描述
t组数据,每组数据给出一个长度为n的序列a和一个数字k。判断a中是否存在一个非空子段使得k在这个子段中出现次数最多。存在输出 YES
,否则输出 NO
。
评测忽略大小写。例如,yEs
、Yes
、yes
、YES
都表是肯定回答。
思路
只要a序列中有k,那么k自己就可以构成一个非空子段,因此本体只需要判断a序列中是否有k即可。
AC代码
#include<bits/stdc++.h>
using namespace std;
int t,n,a,k,f;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&k);f=0;
for(int i=1;i<=n;i++){
scanf("%d",&a);
if(a==k)f=1;
}
if(f)printf("yes\n");
else printf("NO\n");
}
return 0;
}
本题比赛时直接AC
二、Aleksa and Stack
题目描述
有t组数据,每组数据给定n。你构造一个长度为n的数组a,使得该数组满足a[i−1]+a[i−2]∤3×a[i]。
思路
当a为奇数序列时,a[i-1]与a[i-2]都为奇数,所以a[i-1]+a[i-2]为偶数。但a[i]为奇数,所以3xa[i]也为奇数,而偶数必然不被奇数整除,因此本题只需要输出一个长度为n的奇数序列即可。
AC代码
#include<bits/stdc++.h>
using namespace std;
int t,n;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1,j=1;i<=n;i++,j+=2)printf("%d ",j);printf("\n");
}
return 0;
}
这道题一开始没想出来怎么构造数组,所以没做,讲过了之后补ac的。
三、Vasilije in Cacak
题目描述
有t组数据,每组数据给定n,k,x。判断能否在1∼n 中不重复的恰好选出k个数使得这k个数的和为x。
可以选出输出 YES
,否则输出 NO
。
评测忽略大小写。例如,yEs
、Yes
、yes
、YES
都表是肯定回答。
思路
1~n这n个数中取出k个,最小的和为前,k个数之和,最大的和为后k个数之和。
因此,当x < k(k+1)/2或x > k(2n-k+1)/2时,一定不成立。
而在k(k+1)/2~k(2n-k+1)/2之间的和,必然都能被取到。因为若能求和出x,必然能求和出x+1。
AC代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll t,n,k,x;
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld %lld %lld",&n,&k,&x);
if(x<k*(k+1)/2||x>k*(2*n-k+1)/2)printf("NO\n");
else printf("YES\n");
}
return 0;
}
这道题比赛时候没看,上课讲过之后补上的
四、Reverse Madness
题目描述
给一个长度为n的字符串s,以及一个k和两个k大小的数组l,r
保证:l[1]=1,r[k]=n,l[i]<r[i],l[i]=r[i-1]+1
q次操作
每个修改都用一个正整数x来定义:
找出一个索引 i,使得 l[i]<=x<=r[i],让a=min(x,r[i]+l[i]-x),b=max(x,r[i]+l[i]-x)
将字符串s从a到b反转
打印最终结果
思路
每个[l[i],r[i]]区间互不相交。
当子段被反转时,修改x与修改n-x+1是一样的。且对于任意区间,当修改偶数次时相当于没修改,所以只需统计每个点被修改的次数即可。
AC代码
#include <bits/stdc++.h>
#define TIE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
const int N=2e5+5;
int t,n,k,a[N],b[N],cnt[N],q,x;string s;
int main(){
TIE;cin>>t;
while (t--){
cin>>n>>k>>s;memset(cnt,0,sizeof cnt);
for(int i=0;i<k;i++){cin>>a[i];a[i]--;}
for(int i=0;i<k;i++){cin>>b[i];b[i]--;}
cin>>q;
for(int i=0;i<q;i++){cin>>x;cnt[x-1]++;}
string ans="";
for(int i=0;i<k;i++){
string s1=s.substr(a[i],b[i]-a[i]+1);
int sm=0,l=a[i],r=b[i];
for(int j=l;j<=(l+r)/2;j++){
sm+=cnt[j]+cnt[r-j+l];
if(sum&1)swap(s1[j-l],s1[r-j]);
}
ans += s1;
}
cout<<ans<< '\n';
}
return 0;
}
这道题也是比赛的时候没看,上课讲了补上的。
五、Iva & Pav
题目描述
给定n大小的数组a,定义f(l,r)为a[l]&a[l+1]&...&a[r]。
q次查询,每次有k和l,输出最大的r使得f(l,r)>=k.
思路
这道题首先要用前缀和。f[i][j]表示前i个中j个比特出现的次数。若f[r][j]-f[l-1][j]=r-l+1,那么第j个应出现在区间[l,r]的所有元素中。
后面的并没有成功完成,代码也没有写出来。
这道题比赛的时候没看,赛后也没补过。