Codeforces Round #659 (Div. 2)【ABCD】(题解) 涵盖知识点:思维、博弈
比赛链接:传送门
A - Common Prefixes
题意: 构造(n+1)个字符串使得第(i)个和第(i+1)个字符串的最长公共前缀的长度为(a_i)
题解: 一开始全a,后面随便改一改。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=110;
int a[maxn];
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
string s(55,'a');
cout<<s<<"
";
for(int i=1;i<=n;i++){
s[a[i]]++;
if(s[a[i]]=='z'+1)s[a[i]]='a';
cout<<s<<"
";
}
}
return 0;
}
B2 - Koa and the Beach (Hard Version)
题意: 共有(n)片海域,初始深度分别给定。潮汐会以(2k)为周期上下波动影响深度,前(k)秒以(1m/s)的速度加深,后(k)秒以(1m/s)速度变浅。每一秒都可以选择呆在当前海域或前往下一海域,但是当深度大于(l)时就会淹死。问能否到达最后的终点。
题解: 确定所有深度加(k)小于等于(l)的点为安全区,可以在任意的安全区停留任意长的时间。然后尽可能选择最早的不会淹死的时间进入下一节点。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int d[maxn];
int main(){
int t;cin>>t;
while(t--){
int n,k,l;
cin>>n>>k>>l;
vector<int> safe={0};
for(int i=1;i<=n;i++){
cin>>d[i];
if(d[i]+k<=l)safe.push_back(i);
}
safe.push_back(n+1);
bool flag=true;
for(int i=1;i<safe.size()&&flag;i++){
int tide=k,down=-1;
for(int j=safe[i-1]+1;j<safe[i];j++){
tide+=down;
if(down==-1)tide-=max(0,d[j]+tide-l);
if(tide<0||d[j]+tide>l){flag=false;break;}
if(tide==0)down=1;
}
}
puts(flag?"Yes":"No");
}
return 0 ;
}
C - String Transformation 1
题意: 给定两个字符串,每次可以选择一个字母然后把(a)中所有的那个字母变为比他大的另一个字母,问最少几次能把(a)变为(b)。
题解: 贪心,直接按照需求从小到大模拟一遍。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=20;
int c[maxn][maxn];
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
string a,b;
cin>>a>>b;
memset(c,0,sizeof c);
int ans=0;
for(int i=0;i<n;i++){
if(a[i]>b[i]){
puts("-1");
goto st;
}
c[a[i]-'a'][b[i]-'a']++;
}
for(int i=0;i<19;i++){
int tmp=21;
for(int j=i+1;j<20;j++){
if(c[i][j])tmp=min(tmp,j);
}
if(tmp!=21){
ans++;
for(int j=i+1;j<20;j++){
c[tmp][j]+=c[i][j];
}
}
}
cout<<ans<<"
";
st:;
}
return 0;
}
D - GameGame
题意: 博弈,两人拿数,异或值大的胜。
题解: 若所有值的异或值(sum)为(0)则平局。否则只要判断(sum)的最高位。问题转化为谁拿走了奇数个最高位的数字就获胜。如果数字的个数为偶数个,那么最后一次拿的人是后手,显然先手必胜,只要先取一个符合要求的接下来模仿对手即可。接下来考虑数字个数为奇数的情况,若含最高位的数字个数对(4)取模结果为(1),那么先手可以先取一个含最高位的数字,接下来模仿对手的操作。否则先后手交换。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],cnt[2];
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
int sum=0;
for(int i=0;i<n;i++){
cin>>a[i];
sum^=a[i];
}
if(sum==0){
puts("DRAW");
continue;
}
int b=1<<(31-__builtin_clz(sum));
memset(cnt,0,sizeof cnt);
for(int i=0;i<n;i++)cnt[bool(a[i]&b)]++;
if(cnt[1]%4==1||n%2==0)puts("WIN");
else puts("LOSE");
}
return 0;
}