Codeforces Round #605 (Div. 3)题解
A - Three Friends
题意:给出三个人的坐标,然后求出三个人最多移动一单元的情况下,三人坐标位置距离相隔最小值。
解:暴力循环每种移动可能。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
long long ans = 5*10e9;
int a[4];
cin>>a[1]>>a[2]>>a[3];
for(long long i = a[1]-1;i <= a[1]+1;i++)
{
for(long long j = a[2]-1;j <= a[2]+1;j++)
{
for(long long k = a[3]-1;k <= a[3]+1;k++)
ans = min(ans,abs(i-j)+abs(j-k)+abs(i-k));
}
}
printf("%lld\n",ans);
}
return 0;
}
B - Snow Walking Robot
题意:机器人不能再次走同一个单元格(除原点外),给出移动字符序列,然后求出删掉最少字符个数后能使机器人走回原点的序列。
解:只要L、R的个数相同且U、D的个数相同就可以使机器人走回原点。所以删掉多余的字符就可以。
/*
6
LRU
DURLDRUDRULRDURDDL
LRUDDLRUDRUL
LLLLRRRR
URDUR
LLL
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
int a = 0,b = 0,c = 0,d = 0;
string s;
cin>>s;
int len = s.length();
//printf("len = %d\n",len);
for(int i = 0;i < len;i++)
{
if(s[i]=='U') a++;
else if(s[i]=='D') b++;
else if(s[i]=='L') c++;
else if(s[i]=='R') d++;
}
int cnt = abs(a-b)+abs(c-d);
a = min(a,b);
c = min(c,d);
//printf("cnt = %d,a = %d,c = %d\n",cnt,a,c);
if(a==0&&c==0) printf("0\n");
else
{
//printf("%d\n",len-cnt);
if(a == 0)
{
printf("2\n");
printf("LR\n");
}else if(c == 0)
{
printf("2\n");
printf("UD\n");
}else
{
printf("%d\n",len-cnt);
for(int i = 1;i <= a;i++) printf("U");
for(int i = 1;i <= c;i++) printf("L");
for(int i = 1;i <= a;i++) printf("D");
for(int i = 1;i <= c;i++) printf("R");
printf("\n");
}
}
}
return 0;
}
C - Yet Another Broken Keyboard
题意:给你一串只含小写字母字符串,和几个可用字母,求用所给字母能表示所给字符串中的子串数量。
解:从头开始循环一遍,如果存在连续的可以打出的字符,cnt++,如果出现了不能打出的字符时,cnt = 1。每次出现可以打出的字符时,ans+=cnt。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int n,m;
bool vis[30];
long long ans = 0;
memset(vis,0,sizeof(vis));
cin>>n>>m;
string s;
cin>>s;
char tmp;
for(int i = 1;i <= m;i++)
{
cin>>tmp;
getchar();
vis[tmp-'a'] = 1;
}
long long cnt = 1;
if(vis[s[0]-'a'])
{
ans++;
cnt++;
}
for(int i = 1;i < n;i++)
{
if(vis[s[i]-'a'])
{
ans+=cnt++;
}else
{
cnt = 1;
}
}
printf("%lld",ans);
return 0;
}
D - Remove One Element
题意:求删除一个元素后的最大的上升子序列的长度。
解:分别记录第i个数前面的递增个数和后面的递增个数,
最后遍历所有的i,因为只有两种情况值最大:
- 第i个的递增个数
- 当arr[i-1]<arr[i+1]时,不要第i个时(i-1)前面的递增个数 + (i+1)后面的递增个数。
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n;
int a[200005];
int l[200005];
int r[200005];
int main()
{
cin>>n;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
l[i] = 1;
r[i] = 1;
}
int ans = 1;
for(int i = 1;i < n;i++)
{
if(a[i] < a[i+1])
{
l[i+1] = l[i]+1;
}
ans = max(ans,l[i+1]);
}
for(int i = n;i > 1;i--)
{
if(a[i] > a[i-1])
{
r[i-1] = r[i]+1;
}
ans = max(ans,r[i-1]);
}
for(int i = 2;i < n;i++)
{
if(a[i-1] < a[i+1]) ans = max(ans,l[i-1]+r[i+1]);
}
printf("%d",ans);
return 0;
}
E - Nearest Opposite Parity
题意:有一个长度为n的数组 a ,数组坐标从 1 到 n ,假设你现在处于数组中的某一个位置,我们假设这个坐标为 i ,那么:
如果 1<=i−a[i] ,那么你可以从坐标 i 移动到坐标 i−a[i] 位置(花费一步);
如果 i+a[i]<=n ,那么你可以从坐标 i 移动到坐标 i+a[i] 位置(同样花费一步)。
对于从 1 到 n 的所有坐标 i 来说,你想要的知道你最少需要几步可以从坐标 i 移动到一个坐标j ,
且 a[i] 和 a[j] 具有不同的奇偶性(也就是说,如果 a[i] 是偶数,那么 a[j] 就是奇数;如果 a[i] 是奇数,那么 a[j] 就得是偶数)。
解:BFS,参考这里