目录
A. Parkway Walk
(点击可以跳转至题目)
题意:
有一段路,走一步会消耗一个能量(起始能量会给),路中间有座位可以恢复任意能量。求走完路所需要恢复的最小能量值。
思路:
起始能量够走完全程就输出0,不然就直接用距离减去起始能量。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long t,n,m;
cin>>t;
while(t--)
{
cin>>n>>m;
long long sum=0;
while(n--)
{
long long k;
cin>>k;
sum+=k;
}
if(sum<=m)
cout<<0<<endl;
else
cout<<sum-m<<endl;
}
}
B. Promo
题意:
一堆商品在做活动,买x件,其中最便宜的y件可以免费,输出不同x、y最多可以免费的金额。
思路:
先从大到小排,答案就是前x件里面倒序y件的价格和。
不过暴力会T(wa一次)。
所以用前缀和,因为太大没有开long long(wa两次)。
然后i、j这样的索引也要开(wa一次)最后斗胆尝试才过了QAQ
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+3;
long long a[maxn];
long long before[maxn];
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
long long n,q;
cin>>n>>q;
for(long long i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n,cmp);
int j=0;
before[0]=0;
for(long long i=1;i<=n;i++)
{
before[i]=before[i-1]+a[j++];
}
for(long long i=0;i<q;i++)
{
long long x,y;
cin>>x>>y;
cout<<before[x]-before[x-y]<<endl;
}
}
C. awoo's Favorite Problem(!)
题意:
给两个长度为 n 的字符串 s 和 t。两个字符串都是由“a”、“b”或“c”组成。
有两种操作:
1.选择 s 中出现的“ab”并将其替换为“ba”;
2.选择 s 中出现的“bc”并将其替换为“cb”。
不限制操作次数,可以改变字符串 s 使它等于字符串 t 吗
思路1:
我们依次比较,不同就向后寻找需要的字符,只要满足条件没有阻拦因素就交换,否则就是不能通过变换得到两个相同字符串的。
当匹配不成功时:
1.首先 交换串字符 不能为c,因为c无法变成原串想要的a或者b。(cb、ca、cc都是不满足条件的)。
2.如果原串字符是a,(排除1),则交换串字符是b,那没办法了,a只能通过和b交换使自己位置越来越靠后。(ba不能变成ab)-------NO。
3.如果原串字符是b,想得到b的话需要靠a,b可以通过和a交换 使自己向前冲(遇到c阻拦就冲不动啦)。就是aaaaaaab(OK),aaaaacb(NO)。
3.如果原串字符是c,想得到c的话需要靠b,c可以通过和b交换 使自己向前冲(遇到a阻拦就冲不动啦)。就是bbbbbbbc(OK),bbbbbac(NO)。
代码1:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
string s, t;
cin >> n >> s >> t;//把s变成t
int ib = 0, ia = 0,flag=0;
for(int i=0;i<n;i++)
{
ia=max(ia,i);//取最大值是因为前面的比较过了,取i也是可以的,反正循环也会走到正确的ia
ib=max(ib,i);
if(s[i]!=t[i])//不能匹配时
{
if(s[i]=='c')//c想变成a和b都是不可能的
{
flag=1;
break;
}
if(t[i]=='a')
//因为a只能通过交换向后移动,所以之后再怎么变换也不会使当前为a
{
flag=1;
break;
}
if(t[i]=='b')//b可以通过和很多a交换而向前移动(只要没有c阻挠)
{
while(s[ia]=='a'&&ia<n)
ia++;
if(s[ia]=='c'||ia>=n)//遇到了c或者到结尾都只有a一个人
{
flag=1;
break;
}
else
{
swap(s[ia],s[i]);
}
}
else if(t[i]=='c')//c可以通过和很多b交换而向前移动(只要没有a阻挠)
{
while(s[ib]=='b'&&ib<n)
ib++;
if(s[ib]=='a'||ib>=n)//遇到了a或者到结尾都只有b一个人
{
flag=1;
break;
}
else
{
swap(s[ib],s[i]);
}
}
}
}
if(flag)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}
思路2:
1.首先三个字符的个数要相同,这里用到了count函数计数:
在c++的algorithm中,用于在一对迭代器中寻找指定值val出现的次数。
例: count(s.begin().s.end(),val);
2.ab、bc交换意味着b可以前后移动,所以b的位置不重要。统计两个字符串里a、c分别出现的位置。这里是用vector记录的。
因为c可以通过交换向前移动,所以只要 交换串里c的位置 不小于 原串里c的位置就行(毕竟c向后移动是不太行的)。
同理,因为a可以通过交换向后移动,所以只要 交换串里a的位置 不于大 原串里a的位置就行(毕竟a向前移动是不太行的)。
(我的cf怎么又又又又又进不去了)
代码2:
#include <iostream>
#include<cstring>
#include<vector>
using namespace std;
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define PII pair<int,int>
#define ll_INF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
#define io ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
void Solve()
{
int n;
cin >> n;
string s, t;
cin >> s >> t;
for (auto ch : { 'a','b','c' })
{
if (count(s.begin(), s.end(), ch) != count(t.begin(), t.end(), ch))
{
cout << "NO\n";
return;
}
}
string smalls, smallt;//用于比较ac相对位置
vector<int> sa, sc, ta, tc;
for (int i = 0; i < n; i++)
{
if (s[i] == 'a')
{
smalls += s[i]; sa.pb(i);
}
else if (s[i] == 'c')
{
smalls += s[i]; sc.pb(i);
}
if (t[i] == 'a')
{
smallt += t[i]; ta.pb(i);
}
else if (t[i] == 'c')
{
smallt += t[i]; tc.pb(i);
}
}
if (smalls != smallt)
{
cout << "NO\n";
return;
}
for (int i = 0; i < sa.size(); i++)
{
if (sa[i] > ta[i])
{
cout << "NO\n";
return;
}
}
for (int i = 0; i < sc.size(); i++)
{
if (sc[i] < tc[i])
{
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
int main()
{
int T;
cin >> T;
while (T--)
{
Solve();
}
}