比赛链接:Dashboard - Educational Codeforces Round 151 (Rated for Div. 2) - Codeforces
目录:
A. Forbidden Integer
题意:给你三个整数n,k,x,你可以使用1~k中除x以外的任意数字,并且能使用无数次,问你能不能从中选出拼出n的数字。
思路:若x不为1则输出n个1即可,若x为1,只有两种情况是拼不出n的:
①n为奇数且k=2,这说明了我们只能选择数字2,而数字2是拼不出奇数的。
②k等于1,此时我们什么数字都选不了,自然是拼不出n。
排除no的答案后,n为偶数的情况可以用n/2个2拼出,n奇数且n大于等于3的情况可以由n/2-1个2加上一个3来拼出。
代码:
void solve() {
int n,k,x;
cin>>n>>k>>x;
if(x!=1) {
cout<<"YES"<<endl;
cout<<n<<endl;
FOR(1,n) cout<<1<<" \n"[i==n];
}
else if((n%2&&k==2)||k==1) cout<<"NO\n";
else {
cout<<"YES"<<endl;
cout<<n/2<<endl;
FOR(1,n/2) cout<<2<<" ";
cout<<2+(n%2)<<endl;
}
}
B. Come Together
题意:两个人同时从同一地点A出发,前往两个位置B和C,且分别采用步数最短的走法,问你能重叠的路径最多有多少个。
思路:分类讨论,若B点的横坐标和C点的横坐标相对于A点的纵坐标在同一侧,则对于答案的贡献为B点和C点与A的横坐标距离的较小值,也就是“公共横坐标路径”,公共纵坐标路径的贡献的计算同理。
代码:
void solve() {
int ax,ay,bx,by,cx,cy,f1,f2,ans=0;
cin>>ax>>ay>>bx>>by>>cx>>cy;
int x1=abs(ay-by),y1=abs(ay-cy);
int x2=abs(ax-bx),y2=abs(ax-cx);
if((by>ay)==(cy>ay))ans+=min(x1,y1);
if((bx>ax)==(cx>ax))ans+=min(x2,y2);
cout<<ans+1<<endl;
}
C. Strong Password
题意:给定一个仅包含数字的字符串 s ,然后再给定 m 个区间 [li,ri](1<=i<=m),数字第i个位必须在这第i个区间的范围内,问能否从这 m 个区间中分别取出一个合法数字,拼成字符串后其不是字符串 s 的子序列。
思路:首先,对于每一位上数字的数字k,我们从它的范围[li,ri]遍历一遍,在遍历的过程中,若k在字符串中存在,则最优的选法是数字k在未被“删”去的字符串中第一次出现的相同数字的靠后位置。
例如,我们可以选择数字有:1,2,3,字符串s是111222333,我们的最优选择则是数字3,因为选了数字3,子序列的开头必须从标红数字开始——111222333,相当于把这个3前面的数字“111222”都“删”了,不用再考虑了,所以自然是删的越多越好。若我们选择了数字2,则子序列从111222333开始,“删”的数字少了,肯定不如选择数字3。
若字符串s中未被“删”去的序列中找不到k,则直接输出yes。
代码:
void solve() {
string s,t1,t2;
int m,k=0;
cin>>s>>m>>t1>>t2;
FOR(0,m-1) {
int maxx = 0;
for (char j = t1[i]; j <= t2[i]; ++j) {
int tmp = s.find(j, k);
if (tmp>=s.size()) {
cout<<"YES"<<endl;
return;
}
maxx=max(maxx,tmp+1);
}
k = maxx;
}
cout<<"NO"<<endl;
}
D. Rating System
题意:找任意一个可能的值 k ,使得 n 轮比赛后的得分是最大的(得分为累加)。其中需要评分先到达 k,才会使得评分低于 k 后会保持k不变。
思路:可以得出的一个结论是:k一定等于某个前缀。因为若要使得k有意义,则一定要有一个前缀大于等于k,才会使得k有作用,也就是说k小于等于某个前缀,它才有作用。那么不妨让k取最大也就是等于某个前缀,然后枚举每个k作为每个前缀时的最终答案,枚举的答案为前缀加上最大的后缀。
为什么是最大的后缀呢?因为我们在枚举第i个位置作为前缀时,后面i+1~n的位置的负数贡献对于答案是没有意义的,贡献都是0。只有后缀为正数贡献才能使得最终的n发生改变,改变的量为i+1~n中最大的后缀。(注意i=0的情况也要枚举)
代码:
void solve() {
int n,summ=0,maxx=0,ans=0;
cin>>n;
maxh[n+1]=0;
FOR(1,n) {
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
ROF(n,1) {
summ+=a[i];
maxh[i]=max(maxh[i+1],summ);
}
FOR(0,n) {
int k=sum[i]+maxh[i+1];
if(k>maxx) {
maxx=k;
ans=sum[i];
}
}
cout<<ans<<endl;
}