Educational Codeforces Round 63 (Rated for Div. 2)
- A. Reverse a Substring
emmmmm想复杂了,就是找到一组前一个的字典序大于后一个的(使得整个字符串的字典序变小)然后交换即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std ;
const int N = 3e5 + 5 ;
int main(){
char s[N] ;
int n ;
cin >> n ;
cin >> s+1 ;
for (int i = 1 ; i < n ; ++ i){
if (s[i] > s[i+1]){
cout << "YES" << endl ;
cout << i << " " << i+1 << endl ;
return 0 ;
}
}
cout << "NO" << endl ;
return 0 ;
}
B - Game with Telephone Numbers
B题意:给出一串电话数字,然后两个人轮流擦掉数字,A先手,若最后为一个电话号码(以8开头的11位的电话号码)则A胜利打印出YES,(输入的电话号码个数为奇数)。
题解:
若A要胜利必须一直擦掉8前面的数字,若B要胜利则要一直擦掉8
方法一:统计8的个数和8出现的位置,若8的个数大于等于m+1(B擦掉8的个数为m,因为一共有m轮)且第m个8出现的位置要在2*m+1之前。
方法二(简单):直接统计n-10前面8的个数,后面的8太后B不会去擦掉,A也不会去擦,所以没有统计意义,最后8的个数大于游戏轮数加一即可。
方法一:
#include <cstdio>
const int N = 1e5 + 5;
int step[N] ;
int main(){
int n ;
char s[N] ;
scanf("%d",&n) ;
int m = (n-11)/2 ;
int count = 0 , last = 0 ;
for (int i = 0 ; i < n ; ++ i){
scanf ("%c",&s[i]) ;
if (s[i] == '8') {
++ count ;
step[last++] = i ;
}
}
if (count >= m+1){
if (step[m] <= 2*m+1) printf ("YES\n") ;
else printf("NO\n") ;
}
else printf ("NO\n") ;
return 0 ;
}
方法二:
#include <iostream>
#include <cstring>
using namespace std ;
int main(){
int n ;
string s ;
cin >> n >> s ;
int count = 0 ;
for (int i = 0 ; i < n ; ++ i){
if (i < n-10 && s[i] == '8') ++ count ;
}
if (count >= (n-11)/2+1) printf ("YES\n") ;
else printf ("NO\n") ;
return 0 ;
}
C - Alarm Clocks Everywhere
题意:给出n个要响铃的时间点和m个时间间隔,要求输入开始时间和间隔时间,每次闹钟响起的时刻要满足数列n中的时间点。
题解:一直求时间间隔的最大公约数,然后在数列m中找d的因子。
#include <iostream>
#include <algorithm>
using namespace std ;
const int N = 3e5 + 5 ;
typedef long long ll ;
ll a[N] , b[N] ;
int main(){
int n , m ;
cin >> n >> m ;
for (int i = 0 ; i < n ; ++ i) cin >> a[i] ;
for (int i = 0 ; i < m ; ++ i) cin >> b[i] ;
ll d = 0 ;
for (int i = 1 ; i < n ; ++ i){
d = __gcd(d,(a[i]-a[i-1])) ;
}
for (int i = 0 ; i < m ; ++ i) {
if (d % b[i] == 0){
cout << "YES" << endl ;
cout << a[0] << " " << i+1 << endl ;
return 0 ;
}
}
cout << "NO" << endl ;
return 0 ;
}
D - Beautiful Array
题意:给出n个数字和数字x,数列连续的一段可以乘于x也可以不乘,要求找出一段连续数列和的最大值(其中可以有乘于x也可以没有,但是乘于x的要连续)
例如:
dp[0]表示没有乘于x的序列最大值
dp[1]表示正在乘x的最大值
dp[2]表示乘了x的最大值
然后每一次都更新ans最大值即可。
#include <iostream>
#include <algorithm>
using namespace std ;
const int N = 3e5 + 5 ;
typedef long long ll ;
ll a[N] ;
ll dp[3] ;
int n ;
int main(){
int n , x ;
cin >> n >> x ;
ll ans = -1e9 ;
for (int i = 1 ; i <= n ; ++ i){
ll k ;
cin >> k ;
dp[0] = max((ll)0,dp[0]+k) ;
dp[1] = max(dp[0],dp[1]+k*x) ;
dp[2] = max(dp[1],dp[2]+k) ;
ans = max(ans,dp[2]) ;
}
cout << ans << endl ;
return 0 ;
}