涵盖知识点:思维、dp
比赛链接:传送门
A - Common Subsequence
题意: 找串(a,b)的最短公共子序列
题解: 找一个相同的字母即可。若全不同则不存在。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1010;
int a[maxn],b[maxn];
int main(){
int t;cin>>t;
while(t--){
int n,m;
cin>>n>>m;
memset(a,0,sizeof a);
for(int i=0;i<n;i++){
int x;
cin>>x;
a[x]=1;
}
int ans=0;
for(int i=0;i<m;i++){
int x;
cin>>x;
if(a[x]==1){
ans=x;
}
}
if(ans){
cout<<"YES
"<<1<<" "<<ans<<"
";
}
else cout<<"NO
";
}
return 0;
}
B - Sequential Nim
题意: 博弈,每个人可以从含有石子的序号最小的堆中拿走任意正数个石子。
题解: 一般情况下先手必胜,可以每堆都拿到剩1个,然后最后一堆一次性拿完。如果中间存在1个的堆,那么可以一次性拿完前一堆,另一人只能拿完那一堆,回到正常的状态。但是如果开头存在奇数个1个的堆,那么先后手交换。特判一下所有堆都是1的情况。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
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];
}
int cnt=0;
for(int i=1;i<=n;i++){
if(a[i]==1)cnt++;
else break;
}
if(cnt==n)cnt++;
puts(cnt&1?"Second":"First");
}
return 0;
}
C2 - Prefix Flip (Hard Version)
题意: 给定两个二进制串(a,b)。每次选择一个数字,将(a)的前缀各位取反后再倒序。要求在(2n)次操作后将(a)变为(b)。
题解: 先最多花费(n)次将(a)所有位变为相同数字,再从后往前确定每一位的数字。若对应位不同,则对其包含在内的所有前缀进行翻转。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
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];
}
int cnt=0;
for(int i=1;i<=n;i++){
if(a[i]==1)cnt++;
else break;
}
if(cnt==n)cnt++;
puts(cnt&1?"Second":"First");
}
return 0;
}
D - Unmerge
题意: 给定(2n)长度的数组(p),问是否可能为两个长度为(n)的(a,b)合并而成,合并规则大概是依次从(a,b)中第一个未被选用的位置中选择一个较大的数字加入(p)。
题解: 观察(p),按照向右的第一个比当前段最大值大的值进行分段。以([3,2,6,1,5,7,8,4])为例,将其分为([3,2],[6,1,5],[7],[8,4])四段。可以很明显的看出,我们只有将这些段任意组合的结果才可以得到最后的串。所以我们只要判断这些段能否组成长度为(n)即可。dp一下就可以了。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=4010;
vector<int> idx;
int dp[maxn],v[maxn];
int main(){
int t;cin>>t;
while(t--){
idx.clear();
memset(dp,0,sizeof dp);
memset(v,0,sizeof v);
int n;
cin>>n;
int mx=0;
for(int i=0,a;i<2*n;i++){
cin>>a;
if(a>mx){
mx=a;
idx.push_back(i);
}
}
for(int i=0;i<idx.size()-1;i++){
v[i]=idx[i+1]-idx[i];
}
for(int i=0;i<idx.size();i++){
for(int j=n;j>=v[i];j--){
dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
}
}
puts(dp[n]==n?"YES":"NO");
}
return 0;
}