Prob 1. 找出函数的最宽尖峰
题意:求给定数列 A 中先升后降的最长连续子序列,要求 O(n)。
思路:左右各做一遍最长上升子串,求最大和即可。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> nums(n, 0);
for (int i = 0; i < n; ++i)
cin >> nums[i];
vector<int> left(n, 0);
vector<int> right(n, 0);
for (int i = 1; i < n; ++i)
{
if (nums[i] > nums[i - 1])
left[i] = left[i - 1] + 1;
}
for (int i = n - 2; i >= 0; --i)
{
if (nums[i] > nums[i + 1])
right[i] = right[i + 1] + 1;
}
int max = 0, l = -1, r = -1;
for (int i = 0; i < n; ++i)
{
if (left[i] > 0 && right[i] > 0 && left[i] + right[i] > max)
{
max = left[i] + right[i];
l = i - left[i];
r = i + right[i];
}
}
cout << l << " " << r << endl;
return 0;
}
Prob 2. Paragraph
题意:给定一个英文段落(包含 n 个句子)和 m 次查询,每次给定一个句子,求段落中相同单词数量最多的句子。各个英文句子不包含标点,大小写不敏感。
思路:用set或者hashset解决,体力活。
#include <iostream>
#include <string>
#include <set>
#include <unordered_set>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n, m;
char cc;
cin >> n >> m;
vector<unordered_set<string>> setence(0);
vector<string> vec(0);
string str;
getline(cin, str);
for (int k = 0; k < n; ++k)
{
getline(cin, str);
vec.push_back(str);
unordered_set<string> temp;
temp.clear();
string word = "";
for (int i = 0; i < str.size(); ++i)
{
if (str[i] == ' ')
{
if (word.size() > 0)
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
temp.insert(word);
}
word = "";
}
else if (str[i] != ' ')
{
word += str[i];
}
}
if (word.size() > 0)
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
temp.insert(word);
}
setence.push_back(temp);
}
for (int k = 0; k < m; ++k)
{
getline(cin, str);
unordered_set<string> temp;
temp.clear();
string word = "";
for (int i = 0; i < str.size(); ++i)
{
if (str[i] == ' ')
{
if (word.size() > 0)
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
temp.insert(word);
}
word = "";
}
else if (str[i] != ' ')
{
word += str[i];
}
}
if (word.size() > 0)
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
temp.insert(word);
}
word = "";
int index = 0, max = 0;
for (int i = 0; i < n; ++i)
{
int count = 0;
for (auto it = temp.begin(); it != temp.end(); ++it)
{
if (setence[i].find(*it) != setence[i].end())
++count;
}
if (count > max)
{
max = count;
index = i;
}
}
cout << vec[index] << endl;
}
return 0;
}
Prob. 3 绘制括号序列
题意:给定一个合法的括号序列,以字符矩阵的形式翻转后输出。
思路:先遍历一遍统计每个括号在第几层,然后模拟,体力活。
有个坑,看图,红框中的边上不应该有“|”。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str;
cin >> str;
if (str.size() == 0)
return 0;
vector<int> level(str.size(), 0);
int l = 0;
int maxL = 0;
for (int i = 0; i < str.size(); ++i)
{
if (str[i] == '[')
{
++l;
level[i] = l;
if (l > maxL)
maxL = l;
}
if (str[i] == ']')
{
level[i] = l;
--l;
}
}
for (int i = 0; i < str.size(); ++i)
level[i] = maxL - level[i];
--maxL;
for (int i = 0; i < str.size(); ++i)
{
if (str[i] == '[')
{
if (level[i] == maxL || level[i] == level[i-1])
{
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << ' ';
cout << '+';
for (int k = 0; k < 2 * level[i] + 1; ++k)
cout << '-';
cout << '+';
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << ' ';
cout << endl;
}
else
{
for (int j = 0; j < (2 * maxL - 2 * level[i] - 2)/2; ++j)
cout << ' ';
cout << "|+";
for (int j = 0; j < (2 * level[i] + 1); ++j)
cout << '-';
cout << "+|";
for (int j = 0; j < (2 * maxL - 2 * level[i] - 2) / 2; ++j)
cout << ' ';
cout << endl;
}
if (level[i] == level[i + 1])
{
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << " ";
cout << "|";
for (int j = 0; j < 2 * level[i] + 1; ++j)
cout << " ";
cout << "|";
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << " ";
cout << endl;
for (int j = 0; j < 2 * maxL + 3; ++j)
cout << " ";
cout << endl;
}
}
else if (str[i] == ']')
{
if (level[i] == level[i - 1])
{
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << " ";
cout << "|";
for (int j = 0; j < 2 * level[i] + 1; ++j)
cout << " ";
cout << "|";
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << " ";
cout << endl;
}
if (level[i] == maxL || level[i] == level[i+1])
{
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << ' ';
cout << '+';
for (int k = 0; k < 2 * level[i] + 1; ++k)
cout << '-';
cout << '+';
for (int j = 0; j < (2 * maxL - 2 * level[i]) / 2; ++j)
cout << ' ';
cout << endl;
}
else
{
for (int j = 0; j < (2 * maxL - 2 * level[i] - 2) / 2; ++j)
cout << ' ';
cout << "|+";
for (int j = 0; j < (2 * level[i] + 1); ++j)
cout << '-';
cout << "+|";
cout << endl;
}
}
}
return 0;
}
Prob. 4 数列
题意:给定两个数列 A 和 B 以及 q 组查询 (x, y),每次求满足 A[i] >= x 且 B[i] >= y 这样的 i 的数量。
思路:将数列A和B,以及查询q,都根据x排序(y也行),然后按x序查询,对y来说就只有插入,没有删除了,用平衡树可解。
代码:暂无,笔试的时候一直在第三题那个坑里,第四题没做,找机会再补吧。