Educational Codeforces Round 63 (Rated for Div. 2)
A. Reverse a Substring
题意:
给你一串 s,让你判断能否通过反转区间[l,r]的元素,使得反转后的串的字典序小于 s;
如果能,输出 "YES",并输出任意的 l,r,并不需要所输出的 l,r 是所有满足条件的 l',r' 中的字典序最小的;
反之,输出"NO";
例如,如果串 s = "abaa"
你可以反转[2,3]得到 "aaba"
也可以反转[2,4]得到字典序更小的 "aaab"
输出其中一个答案即可;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define INFull ~0ULL 5 #define ll long long 6 #define ull unsigned long long 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const int maxn=3e5+50; 9 10 int n; 11 char s[maxn]; 12 13 void Solve() 14 { 15 int len=strlen(s+1); 16 int ans=len+1; 17 for(int i=2;i <= len;++i) 18 if(s[i] < s[i-1])//求出第一个下降的位置 19 { 20 ans=i; 21 break; 22 } 23 if(ans == len+1)//如果没找到下降的位置 24 printf("NO\n"); 25 else 26 { 27 printf("YES\n"); 28 printf("%d %d\n",ans-1,ans);//反转区间[ans-1,ans] 29 } 30 } 31 int main() 32 { 33 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 34 scanf("%d",&n); 35 scanf("%s",s+1); 36 Solve(); 37 return 0; 38 }
思考:
如果题干改为求反转区间[l,r]使得得到的串的字典序最小呢?
该怎么求呢?
B. Game with Telephone Numbers
题意:
给出你一个包含 n 个数字的串 s(n为奇数);
Vasya 和 Petya 个从中选取 (n-11)/2 个数字,删去,游戏从Vasya开始;
问 Vasya 能否必胜,必胜的条件是,删除后的串,s[0]='8';
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define INFull ~0ULL 5 #define ll long long 6 #define ull unsigned long long 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const int maxn=3e5+50; 9 10 int n; 11 char s[maxn]; 12 13 char* Solve() 14 { 15 int len=strlen(s); 16 int need=(n-11)/2;//每人需要删除need元素 17 int tot8=0;//s中'8'的总个数 18 19 for(int i=0;i < len;++i) 20 if(s[i] == '8') 21 tot8++; 22 if(tot8 <= need)//8的个数小于等于删除的个数 23 return "NO"; 24 25 //最坏的情况是,Petya删除need个8 26 //那么,Vasya就需要将第need+1个8前的其他数字都删去 27 int tot=0;//第need+1个8前的非'8'得个数 28 int cur=need+1; 29 for(int i=0;cur > 0 && i < len;++i) 30 { 31 if(s[i] != '8') 32 tot++; 33 else 34 cur--; 35 } 36 if(tot <= need)//可以删除这tot个非'8'数 37 return "YES"; 38 else 39 return "NO"; 40 } 41 int main() 42 { 43 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 44 scanf("%d",&n); 45 scanf("%s",s); 46 printf("%s\n",Solve()); 47 return 0; 48 }
C. Alarm Clocks Everywhere
题意:
Ivan 在睡觉前定了闹铃;
闹铃在 a 时刻开始出声,每隔 b 时刻响一次;
Ivan 需要闹铃在 x1,x2,....,xn 时刻提醒他;
给出你 x1,x2,....,xn 和闹铃的间隔时刻 p1,p2,....,pm;
假设闹钟在 a 开始出声,能否在给出的时间间隔内使闹钟响的时刻满足Ivan的需求;
如果能,输出开始出声的时刻a和时间间隔对应在在p中的下标;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define INFull ~0ULL 5 #define ll long long 6 #define ull unsigned long long 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const int maxn=3e5+50; 9 10 int n,m; 11 ll x[maxn]; 12 ll p[maxn]; 13 14 ll GCD(ll a,ll b) 15 { 16 return a == 0 ? b:GCD(b%a,a); 17 } 18 19 char* Solve() 20 { 21 ll gcd=x[2]-x[1]; 22 for(int i=3;i <= n;++i) 23 gcd=GCD(gcd,x[i]-x[i-1]);//求所有时间间隔的GCD 24 int ans=0; 25 for(int i=1;i <= m;++i) 26 if(gcd%p[i] == 0)//如果找到gcd的因子 27 { 28 ans=i; 29 break; 30 } 31 if(ans == 0) 32 printf("NO\n"); 33 else 34 { 35 printf("YES\n"); 36 printf("%I64d %d\n",x[1],ans);//从x[1]时刻开始,每隔p[ans]时刻提醒一次可以满足条件 37 } 38 } 39 int main() 40 { 41 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 42 scanf("%d%d",&n,&m); 43 for(int i=1;i <= n;++i) 44 scanf("%lld",x+i); 45 for(int i=1;i <= m;++i) 46 scanf("%lld",p+i); 47 Solve(); 48 return 0; 49 }