声明
题解包含以下内容:
- (相对)高级的 C++ 模板及语法技巧
- 仅适用于 C++20 标准的代码
- 强烈的个人代码风格和 Modern C++ 范式追求
- 泛滥的标准库函数
换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。
【id:97】【20分】A. 数据排序(函数模板)
题目描述
编写一个进行升序排序的函数模板,其中数组为具有n个元素,类型为T。
注意:必须使用模板函数
输入
第一行输入t表示有t个测试实例
第二行先输入一个大写字母表示数组类型,I表示整数类型,C表示字符型,S表示字符串型,D表示双精度数类型;然后输入n表示数组长度。
第三行输入n个数据
依次输入t个实例
输出
每行输出一个结果
样例
输入样例1 | 输出样例1 |
---|---|
4 I 10 15 3 51 27 9 35 78 14 65 8 D 3 -11.3 25.42 13.2 C 6 a b g e u q S 4 sandy david eason cindy | 3 8 9 14 15 27 35 51 65 78 -11.3 13.2 25.42 a b e g q u cindy david eason sandy |
Answer
#include <bits/stdc++.h>
using namespace std;
template<typename T, typename _Pred>
T& my_sort( T& arr, _Pred p )
{
std::sort( begin( arr ), end( arr ), move( p ) );
return arr;
}
template<typename T>
vector<T> arr_generator( size_t __n ) {
vector<T> arr; arr.reserve( __n );
for ( size_t _ = 0; _ < __n; ++_ ) {
T tmp {}; cin >> tmp;
arr.push_back( move( tmp ) );
}
return arr;
}
template<typename T>
ostream& operator<<( ostream& os, const vector<T>& vec )
{
for ( const auto& e : vec )
os << e << " ";
return os;
}
template<typename T>
void foo()
{
size_t scale {}; cin >> scale;
auto arr = arr_generator<T>( scale );
cout << my_sort( arr, less<T>() ) << endl;
}
int main()
{
size_t t; cin >> t;
while ( t-- ) {
size_t scale {};
switch ( char order; (cin >> order, order) ) {
case 'D': {
foo<double>();
} break;
case 'I': {
foo<int>();
} break;
case 'C': {
foo<char>();
} break;
case 'S': {
foo<string>();
} break;
default:
assert( false );
break;
}
}
}
【id:98】【20分】B. 元素查找(函数模板)
题目描述
编写一个在数组中进行查找的函数模板,其中数组为具有n个元素,类型为T,要查找的元素为key。
注意:必须使用模板函数
输入
第一行输入t表示有t个测试实例
第二行先输入一个大写字母表示数组类型,I表示整数类型,D表示双精度数类型,C表示字符型,S表示字符串型;然后输入n表示数组长度。
第三行输入n个数据
第四行输入key
依次输入t个实例
输出
每行输出一个结果,找到输出key是数组中的第几个元素(从1开始),找不到输出0
样例
输入样例1 | 输出样例1 |
---|---|
4 I 5 5 3 51 27 9 27 D 3 -11.3 25.42 13.2 2.7 C 6 a b g e u q a S 4 sandy david eason cindy cindy | 4 0 1 4 |
Answer
#include <bits/stdc++.h>
using namespace std;
template<typename T, typename U>
requires is_same_v<typename T::value_type, U>
size_t my_finder( const T& arr, U ele )
{
auto iter = find( begin( arr ), end( arr ), move( ele ) );
return iter == end( arr ) ? 0 : 1 + distance( begin( arr ), iter );
}
template<typename T>
vector<T> arr_generator( size_t __n ) {
vector<T> arr; arr.reserve( __n );
for ( size_t _ = 0; _ < __n; ++_ ) {
T tmp {}; cin >> tmp;
arr.push_back( move( tmp ) );
}
return arr;
}
template<typename T>
ostream& operator<<( ostream& os, const vector<T>& vec )
{
for ( const auto& e : vec )
os << e << " ";
return os;
}
template<typename T>
void foo()
{
size_t scale {}; cin >> scale;
auto arr = arr_generator<T>( scale );
T target_ele {}; cin >> target_ele;
cout << my_finder( arr, target_ele ) << endl;
}
int main()
{
size_t t; cin >> t;
while ( t-- ) {
size_t scale {};
switch ( char order; (cin >> order, order) ) {
case 'D': {
foo<double>();
} break;
case 'I': {
foo<int>();
} break;
case 'C': {
foo<char>();
} break;
case 'S': {
foo<string>();
} break;
default:
assert( false );
break;
}
}
}
【id:99】【20分】C. 谁的票数最高(函数模板)
题目描述
某小镇要票选镇长,得票最高者当选。但由于投票机制不健全,导致每届投票时,候选人在投票系统的识别码类型不一致。请编写函数模板,能针对多种类型的数据,查找出得票最高的元素。其中,每届投票的选票有n张,识别码类型为T
注意:必须使用模板函数
输入
第一行输入t表示有t个测试实例
第二行先输入一个大写字母表示识别码类型,I表示整数类型,C表示字符型,S表示字符串型;然后输入n表示数组长度。
第三行输入n个数据
依次输入t个实例
输出
每行输出一个结果,分别输出当选者的识别码和得票数,以空格分开。
样例
输入样例1 | 输出样例1 |
---|---|
3 I 10 5 3 5 2 9 7 3 7 2 3 C 8 a b a e b e e q S 5 sandy david eason cindy cindy | 3 3 e 3 cindy 2 |
Answer
#include <bits/stdc++.h>
using namespace std;
template<typename T>
pair<T, size_t> my_counter( const vector<T>& arr )
{
unordered_map<T, size_t> counter_map;
for ( const auto& e : arr )
++counter_map[e];
auto iter = max_element(
counter_map.begin(), counter_map.end(),
[]( auto&& a, auto&& b ) -> bool {
return a.second < b.second;
}
);
return *iter;
}
template<typename T>
ostream& operator<<( ostream& os, const pair<T, size_t> par )
{
return os << par.first << " " << par.second;
}
template<typename T>
vector<T> arr_generator( size_t __n ) {
vector<T> arr; arr.reserve( __n );
for ( size_t _ = 0; _ < __n; ++_ ) {
T tmp {}; cin >> tmp;
arr.push_back( move( tmp ) );
}
return arr;
}
template<typename T>
ostream& operator<<( ostream& os, const vector<T>& vec )
{
for ( const auto& e : vec )
os << e << " ";
return os;
}
template<typename T>
void foo()
{
size_t scale {}; cin >> scale;
auto arr = arr_generator<T>( scale );
cout << my_counter( arr ) << endl;
}
int main()
{
size_t t; cin >> t;
while ( t-- ) {
size_t scale {};
switch ( char order; (cin >> order, order) ) {
case 'D': {
foo<double>();
} break;
case 'I': {
foo<int>();
} break;
case 'C': {
foo<char>();
} break;
case 'S': {
foo<string>();
} break;
default:
assert( false );
break;
}
}
}
【id:324】【20分】D. 指定类型与区间排序(函数模板)
题目描述
现在有int、string、float,3种类型的数据需要排序
每次输入数据类型及n个数据,并指定排序区间[beg, end),请你对该区间内的数据进行排序并输出
(可以使用系统排序函数)
输入
第1行:一个正整数t,表示测试次数
以下t行,每行输入:type n [beg,end) : n个数据(用空格分隔)…
(注意beg和end可以为任何值,且不一定有beg<=end成立。如果区间越界,则超出部分不进行排序:
比如n=10, 输入区间为[-10,5),则只对合法区间[0,5)排序)
输出
参见样例输出
样例
输入样例1 | 输出样例1 |
---|---|
3 int 5 [2,4) : 5 4 3 2 1 string 3 [-4,4) : b c a float 3 [0,4) : 3.3 1.1 2.2 | [5, 4, 2, 3, 1] [a, b, c] [1.1, 2.2, 3.3] |
提示
排序区间[beg, end)指的是:从下标为beg的数据开始,到下标为end-1的数据截止(下标从0开始)
Answer
#include <bits/stdc++.h>
using namespace std;
enum class DataType { Integer, String, Float };
struct DataInterval {
DataType type;
int range_start;
int range_end;
vector<string> values;
};
DataInterval parser( const string& line ) {
regex pattern( R"((\w+)\s+(\d+)\s+\[(\-?\d+),(\-?\d+)\)\s+:\s+((\S+\s*)+))" );
smatch match;
DataInterval info;
if ( regex_search( line, match, pattern ) ) {
if ( auto type_str = match.str( 1 );
type_str == "int" )
info.type = DataType::Integer;
else if ( type_str == "string" )
info.type = DataType::String;
else info.type = DataType::Float;
info.range_start = stoi( match.str( 3 ) ); // 区间段
info.range_end = stoi( match.str( 4 ) );
string values_str = match.str( 5 );
regex values_pattern( R"(\S+)" );
// 数据区间
for ( auto iter = sregex_iterator( values_str.begin(), values_str.end(), values_pattern ); iter != sregex_iterator {}; ++iter )
info.values.push_back( iter->str() );
}
return info;
}
template<typename T>
ostream& operator<<( ostream& os, const vector<T>& arr )
{
os << '[';
for ( size_t i = 0; i < arr.size(); ++i )
os << arr[i] << (i == arr.size() - 1 ? ""sv : ", "sv);
return os << ']';
}
int main()
{
size_t t {}; cin >> t;
getchar(); // endline
while ( t-- ) {
string line; getline( cin, line );
DataInterval info = parser( line );
switch ( info.type ) {
case DataType::Integer: {
vector<int> values;
transform( info.values.begin(), info.values.end(),
back_inserter( values ), []( auto&& str ) { return stoi( str ); } );
if ( info.range_start < 0 )
info.range_start = 0;
if ( info.range_end > info.range_start )
sort( values.begin() + info.range_start,
info.range_end > values.size() ? values.end() : values.begin() + info.range_end );
cout << values << endl;
} break;
case DataType::String: {
if ( info.range_start < 0 )
info.range_start = 0;
if ( info.range_end > info.range_start )
sort( info.values.begin() + info.range_start,
info.range_end > info.values.size() ? info.values.end() : info.values.begin() + info.range_end );
cout << info.values << endl;
} break;
case DataType::Float: {
vector<float> values;
transform( info.values.begin(), info.values.end(),
back_inserter( values ), []( auto&& str ) { return static_cast<float>(stod( str )); } );
if ( info.range_start < 0 )
info.range_start = 0;
if ( info.range_end > info.range_start )
sort( values.begin() + info.range_start,
info.range_end > values.size() ? values.end() : values.begin() + info.range_end );
cout << values << endl;
} break;
default:
assert( false );
break;
}
}
}
【id:331】【20分】E. 抢票验证码(函数模板)
题目描述
对于某抢票系统,存在一个长度为六的验证码,验证码可以为整形,字符型,浮点型,我们认为验证码是有效的当且仅当验证码是非递减序列(递增或者相等)。现请你利用函数模板,完成对验证码的检验
输入
测试数据有多组,每组测试数据给出验证码类型以及一串验证码
输出
输出验证的结果
样例
输入样例1 | 输出样例1 |
---|---|
c a b c d e f i 1 2 3 4 5 6 f 1.1 1.2 1.3 4 5 6 c f e v a c s | Valid Valid Valid Invalid |
Answer
#include <bits/stdc++.h>
using namespace std;
template<typename T>
bool verify_checker( const vector<T>& code )
{
return is_sorted( code.begin(), code.end() );
}
vector<string> spliter( const string& str ) {
regex pattern( "\\s+" );
return { sregex_token_iterator( str.begin(), str.end(), pattern, -1 ), sregex_token_iterator() };
}
int main()
{
char order {};
while ( cin >> order ) {
cin.ignore( (numeric_limits<streamsize>::max)(), '\n' );
string line_input; getline( cin, line_input );
vector<string> origin_code = spliter( line_input );
order = tolower( order );
if ( order == 'c' ) {
vector<char> code;
transform( origin_code.begin(), origin_code.end(),
back_inserter( code ), []( auto&& e ) -> char { return e.front(); } );
cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
} else if ( order == 'i' ) {
vector<int> code;
transform( origin_code.begin(), origin_code.end(),
back_inserter( code ), []( auto&& e ) -> int { return stoi( e ); } );
cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
} else {
vector<float> code;
transform( origin_code.begin(), origin_code.end(),
back_inserter( code ), []( auto&& e ) -> float { return static_cast<float>(stod( e )); } );
cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
}
}
}