Codeforces Round #753
A. Linear Keyboard
题意
先给定26个字母的排列顺序 再给一个字符串s 字符串s的代价为s中相邻两个字母在26个字母排列顺序的距离 求s的代价总和
思路
暴力模拟
代码
#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll t,n,k,te,a[30];
string s,st;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
ll ans=0;
cin>>st>>s;
for(int i=0;i<st.size();i++)
{
a[st[i]-'a']=i;
}
for(int i=1;i<s.size();i++)
{
ans+=abs(a[s[i]-'a']-a[s[i-1]-'a']);
}
cout<<ans<<endl;
}
return 0;
}
B. Odd Grasshopper
题意
跳跃步长开始为1 然后每次不断增加1(步长依次为1,2,3…)
如果当前点是偶数 就向左跳 如果当前点是奇数 就向右跳
现在给出起始点x 和跳跃的次数n 问n次跳跃后会在哪个点
思路
打表找出规律 每第4个数都会变成x 第2个数会根据开始位置的奇偶变成 x-1或者x+1 其它两位数字在根据奇偶定下初始位置后 给据每经过4个数 就变化4的规律
代码
#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll t,x,n,k;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>x>>n;
/*ll t=x;
for(int i=1;i<=n;i++)
{
if(t%2==0)
t-=i;
else
t+=i;
cout<<t<<": "<<i<<endl;
}
cout<<endl;*/
//打表
ll cnt=n/4,te=n%4;
if(te==0)
cout<<x<<endl;
else if(te==2)
{
if(x%2)
{
cout<<x-1<<endl;
}
else
cout<<x+1<<endl;
}
else if(te==1)
{
if(x%2)
cout<<(x+1)+4*cnt<<endl;
else
cout<<(x-1)-4*cnt<<endl;
}
else
{
if(x%2)
cout<<x-4*(cnt+1)<<endl;
else
cout<<x+4*(cnt+1)<<endl;
}
}
return 0;
}
C. Minimum Extraction
题意
给一个数组 每次找到最小的一个数 然后其余数-最小数 然后删除这个最小数 问这样操作找到数组的最小值最大是多少
思路
下一次的最小值是这一次次最小值与最小值之差 问题转变成排序后 不断找相邻的差值 就能得出最小值的所有可能 找最大值
代码
#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll t,x,n,k,a[N],te,ans;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
ll ans=a[0];
for(int i=1;i<n;i++)
{
ans=max(ans,a[i]-a[i-1]);
}
cout<<ans<<endl;
}
return 0;
}
D. Blue-Red Permutation
题意
给一个长度为n的数组a 数组的每位有一个颜色 蓝色表示这个数可以不断减1 红色表示这个数可以不断加1 问这个数组最后是否能变成包含1-n所有数字的数组(顺序可以乱 每个数出现一次)
思路
贪心的想法去向 能组成符合的数组 最低要求是蓝色组成1到蓝色个数的数 红色组成后面大的数 达成这个要求的就行
代码
#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#include<set>
#include<queue>
#include<stack>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll t,x,n,k,a[N],te,ans;
string s;
vector<ll> vr,vb;
bool cmp(ll aa,ll bb)
{
return aa>bb;
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
vr.clear();
vb.clear();
cin>>n;
for(int i=0; i<n; i++)
cin>>a[i];
cin>>s;
for(int i=0; i<s.size(); i++)
{
if(s[i]=='B')
vb.push_back(a[i]);
else
vr.push_back(a[i]);
}
sort(vr.begin(),vr.end(),cmp);
sort(vb.begin(),vb.end());
int flag=1;
for(int i=0; i<vb.size(); i++)
{
if(vb[i]<i+1)
{
flag=0;
break;
}
}
if(flag==0)
cout<<"NO\n";
else
{
for(int i=0; i<vr.size(); i++)
{
if(vr[i]>n-i)
{
flag=0;
break;
}
}
if(flag)
cout<<"YES\n";
else
cout<<"NO\n";
}
}
return 0;
}
E. Robot on the Board 1
题意
给定n行m列的方格 再给定可以含上下左右走指令的字符串 问起点定在哪 才能执行更多的移动指令且不超过方格
思路
分为横向和竖向的两个方向不断记录执行每个指令后的上下左右四个方向的历史最值 当某个方向的跨越长度超过方格大小就表示无法执行后面的指令了
代码
#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll t,x,n,m;
string s;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n>>m;
cin>>s;
int maxx=0,minx=0,maxy=0,miny=0;
int dx=0,dy=0;
int ansx=1,ansy=1;
for(int i=0;i<s.size();i++)
{
if(s[i]=='R')
{
dx++;
maxx=max(dx,maxx);
}
else if(s[i]=='L')
{
dx--;
minx=min(dx,minx);
}
else if(s[i]=='U')
{
dy++;
maxy=max(dy,maxy);
}
else
{
dy--;
miny=min(dy,miny);
}
if(maxx-minx+1>m||maxy-miny+1>n)
break;
ansx=maxy+1;
ansy=1-minx;
}
cout<<ansx<<" "<<ansy<<endl;
}
return 0;
}