CF竞赛必备,C++动态数组(vector)赋值全攻略
在CF竞赛中,C++动态数组vector是高效处理数据的必备工具,掌握其赋值方法对提升解题效率至关重要,常见赋值方式丰富多样:初始化时可直接用列表赋值,如vector v={1,2,3};通过push_back()逐个添加元素,适配动态输入场景;assign()方法可批量设定元素值或拷贝其他容器元素;还能通过拷贝构造或赋值运算符直接复制已有vector;emplace_back()则能原地构造元素,比push_back更高效,竞赛中需根据数据规模和场景选择合适方法,兼顾速度与内存优化,助力快速实现解题逻辑。
在Codeforces(CF)算法竞赛中,C++的vector作为动态数组的核心实现,是处理可变长度数据的必备工具,熟练掌握动态数组的赋值技巧,不仅能提升代码编写效率,还能避免常见的运行时错误,本文将从基础到进阶,结合竞赛场景全面解析vector的赋值方法。
基础初始化赋值:从固定数据到默认填充
列表初始化:直观定义已知元素
当你明确知道动态数组的初始元素时,列表初始化是最简洁的方式,这种方法适合小规模固定数据的场景,比如竞赛中初始化测试用例或预设值:

#include <vector>
using namespace std;
int main() {
// 初始化包含1、3、5、7的动态数组
vector<int> nums = {1, 3, 5, 7};
return 0;
}
指定大小与默认值:批量初始化避免垃圾值
竞赛中常需要创建固定大小且元素统一的数组(如全0数组),此时可以通过构造函数直接指定大小和默认值,避免手动循环赋值:
// 创建包含10个元素的数组,每个元素初始化为0 vector<int> nums(10, 0); // 创建包含5个字符串的数组,每个元素为"CF" vector<string> strs(5, "CF");
直接赋值与拷贝:复用已有数据
整体拷贝赋值:快速复制整个数组
如果你需要复用另一个动态数组的所有元素,可以直接用赋值运算符完成拷贝,生成一个完全独立的副本:
vector<int> old_nums = {2, 4, 6};
// 拷贝old_nums的所有元素到new_nums
vector<int> new_nums = old_nums;
assign方法:灵活批量赋值
assign方法比直接赋值更灵活,支持三种赋值方式:
- 按元素个数+默认值赋值:
vector<int> nums; // 赋值5个元素,每个元素为1 nums.assign(5, 1);
- 按迭代器范围拷贝(适合部分复制):
vector<int> old_nums = {1,2,3,4,5}; vector<int> new_nums; // 拷贝old_nums中第2到第4个元素(左闭右开) new_nums.assign(old_nums.begin()+1, old_nums.end()-1);
遍历输入赋值:竞赛高频场景
竞赛中最常见的需求是读取用户输入并赋值给动态数组,这里有两种高效方式:
push_back逐个添加:未知数据量首选
当你不确定输入数据的数量(或数据量较小)时,用push_back动态添加元素是最稳妥的选择:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums;
// 读取n个整数并添加到数组
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
nums.push_back(x);
}
return 0;
}
resize后下标赋值:已知数据量更高效
如果提前知道输入数据的数量,先通过resize固定数组大小,再用下标直接赋值,避免push_back的自动扩容开销,适合大数据量场景:
int n;
cin >> n;
vector<int> nums(n); // 提前分配n个元素的空间
for (int i = 0; i < n; ++i) {
cin >> nums[i]; // 直接通过下标赋值
}
高效赋值进阶技巧:优化竞赛性能
emplace_back替代push_back:减少拷贝开销
emplace_back直接在数组末尾构造元素,避免了push_back可能产生的拷贝或移动操作,在处理自定义类型或大数据时效率更高:
// 直接构造整数10并添加到数组,无需临时拷贝 nums.emplace_back(10);
fill批量填充:快速重置数组元素
如果需要将数组所有元素统一设置为某个值,使用algorithm库中的fill函数比手动循环更简洁高效:
#include <algorithm> // 将nums中所有元素设置为0 fill(nums.begin(), nums.end(), 0);
从其他容器赋值:兼容数组、列表等
vector支持从普通数组、list等容器赋值,只需传入迭代器范围:
// 从普通数组赋值
int arr[] = {1,2,3};
vector<int> nums(arr, arr + 3);
// 从list赋值
list<int> l = {4,5,6};
nums.assign(l.begin(), l.end());
常见误区与注意事项
- 避免未初始化直接用下标:未添加元素的
vector为空,直接用nums[0] = 1会触发越界错误,必须先resize或push_back元素后才能使用下标。 - 提前
reserve减少扩容:频繁push_back会触发自动扩容(每次扩容通常翻倍),若已知数据量,提前用nums.reserve(n)预留空间,可减少内存分配次数,提升性能。 - 区分
resize与reserve:resize会改变数组大小并初始化元素,reserve仅预留空间,不改变数组实际大小。
在CF竞赛中,动态数组的赋值没有“最优解”,只有“最适合场景的解”:初始化用列表或指定大小,输入用push_back或resize下标,拷贝用assign,高效赋值用emplace_back和fill,掌握这些技巧,能让你的代码更简洁、高效,轻松应对竞赛中的各种数据处理需求。
