A
点击此处查看对应的题目.
本题涉及算法:贪心
本题结果是想要让题目给出的数字变为0,通过将最后一位减为0来实现,那么其实也就很简单了。如果只有最后一位则直接得到最后一位的值即为答案,若其他位有数字则将其他位置的数字换到最后一位即可,所以总操作数就是所有位的值相加和交换的次数的总和。
时间复杂度 O ( n ) O(n) O(n)
#include<bits/stdc++.h>
using namespace std;
const int N = 500;
int n;
void solve()
{
string s;
int cnt = 0;
cin >> n >> s;
for(int i = 0;i < n;i ++){
if(i == n - 1 && s[i] != '0') cnt += (s[i] - '0');
else if(i != n - 1 && s[i] != '0' ) cnt += ((s[i] - '0') + 1);
}
cout << cnt << '\n';
}
int main()
{
int t;
cin >> t;
while(t -- ){
solve();
}
return 0;
}
B
点击此处查看对应的题目.
本题涉及算法:贪心
本题的任务是用交换相邻元素的方式处理题目给出的a,b数组,使得a字典序小于b。
首先分析题目条件,题目给出的a,b数组实际上是一个奇数数组,一个偶数数组,且元素各不相同。由于 ( 1 < a i < 2 ∗ n ) ( 1 < b i < 2 ∗ n ) ( 1<a_i<2*n)(1<b_i<2*n) (1<ai<2∗n)(1<bi<2∗n),所以所有元素值作为下标放在一起时是正好填满2*n的。
因为数组a是奇数而数组b是偶数,所以无论我们如何执行操作,它们在第一个位置都是不同的。为了使第一个数组按字典序小于第二个我们需要做的事是令第一个元素小于b数组的第一个元素,使第i个元素后移动到第一位置,我们可以对元素执行操作i−1,i−2,……2, 1,这是最优的。那么答案就是i+j−2对所有ai, bj的最小值,使ai<bj。
下面讲一下具体做法:我们将从最大到最小的数开一个order数组存储所有值的再数组中的顺序。设l是已经考虑过的数列b中最左边的数。如果i是偶数,我们设l为 m i n ( l , o r d e r i ) min(l,order_i) min(l,orderi)如果i是奇数,我们将答案设为 m i n ( r e s , o r d e r i + l ) min(res,order_i+l) min(res,orderi+l)。
时间复杂度 O ( n ) O(n) O(n)
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10,INF = 1e9;
int n;
int order[N];
void solve()
{
int n,x;
cin >> n;
for(int i = 0;i < n;i ++){
cin >> x;
order[x] = i;
}
for(int i = 0;i < n;i ++){
cin >> x;
order[x] = i;
}
int minn = INF,l = n;
for(int i = 2 * n;i > 0;i --){
if(i % 2) minn = min(minn,order[i] + l);
else l = min(l,order[i]);
}
cout << minn << '\n';
}
int main()
{
int t;
cin >> t;
while(t -- ){
solve();
}
return 0;
}