PAT 1093 Count PAT’s and PAT 1101 Quick Sort
这两道题属于同一种类型:直接暴力会超时,需要借助一些技巧。参考书籍:刘凡《算法笔记》的P147 活用递归。
1093 Count PAT’s
目标:给定一个字符串,输出其能组成多少个PAT。
思路:
- 从左往右扫描字符数组,记录当前下标 i 及以前有多少个P: p[i]
- 再从右往左扫描字符数组,记录当前下标 i 及之后有多少个T: t[i]
- 最后再从头扫描一遍数组,寻找A。当前A的下标 i 能够构成 p[i] * t[i] 个PAT。计算过程中记得模上 1000000007,防止溢出。
#include<iostream>
#include<string>
using namespace std;
#define MAXN 100010
#define MODE 1000000007
int p[MAXN];
int t[MAXN];
int main(){
string s;
cin >> s;
int l = s.length();
p[0] = (s[0] == 'P') ? 1 : 0;
for(int i = 1; i < l; i++){
if (s[i] == 'P') p[i] = p[i-1] + 1;
else p[i] = p[i-1];
}
t[l - 1] = (s[l - 1] == 'T') ? 1 : 0;
for (int i = l - 2; i >= 0; i--){
if (s[i] == 'T') t[i] = t[i+1] + 1;
else t[i] = t[i+1];
}
int res = 0;
for (int k = 1; k < l - 1; k++){
if (s[k] == 'A')
res = (res + p[k] * t[k])% MODE;
}
cout << res << endl;
return 0;
}
1101 Quick Sort
1101这道题是寻找作为快排的pivot,其特征表现为: pivot ① 左边的数都小于它 ② 右边的数都大于它。
思路:
- 从左往右扫描一遍数组,判断当前下标对应的值是否比前面最大的都大,用一个状态数组max_index记录。1表示当前下标对应的值满足成为pivot的条件①,0表示不满足成为pivot。
- 从右往左扫描一遍数组,判断当前下标对应的值是否比后面最小的都小,用一个状态数组min_index记录。1表示当前下标对应的值满足成为pivot的条件②,0表示不满足成为pivot。
- 最后再扫描一遍数组,只有当同一下标的 max_index 和 min_index 的值同时为1的时候,即满足成为pivot的两个条件,用结果数组记录该值。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N;
#define MAXN 100010
int a[MAXN];
vector<int> res;
int max_index[MAXN];
int min_index[MAXN];
int main(){
cin >> N;
for (int i = 0; i < N; i++){
cin >> a[i];
}
// 当前下标元素前面是否有数大于
int maxv = a[0];
max_index[0] = 1; //单独处理边界的情况
for (int j = 1; j < N; j++){
if (maxv > a[j]) max_index[j] = 0; // 不可能是pivot
else {
maxv = a[j];
max_index[j] = 1;
}
}
int minv = a[N - 1];
min_index[N - 1] = 1; // 单独处理边界
for (int k = N - 2; k >= 0; k--){
if(minv < a[k]) min_index[k] = 0; // 不可能是pivot
else{
minv = a[k];
min_index[k] = 1;
}
}
int count = 0;
for (int i = 0; i < N; i++){
if(max_index[i] && min_index[i]){
// 可以为pivot的情况
count++;
res.push_back(a[i]);
}
}
sort(res.begin(), res.end());
printf("%d\n", count);
for(int j = 0; j < count - 1 ; j++)
printf("%d ", res[j]);
if (count != 0)
printf("%d", res[count - 1]);
printf("\n");
return 0;
}
坑边闲话:
- 1101 有个测试用例,输入中没有一个是pivot。输出的第二行需要输出一个换行符。不然,会有 格式错误 过不了该样例
- 对vector 进行排序
sort(v.begin(), v.end())
- 类型表示范围:int -2147483648~2147483647 long long -9223372036854775807~9223372036854775808