一些值得注意的STL使用,用错了可能就复杂度错误了

前言

一些见到(或看到别人,或写了)的问题就记一下吧

正文

lower_bound

STL分为两类,一类是支持随机访问的,另一类是不支持随机访问的。而不支持随机访问的,若使用lower_bound函数,请一定要使用.... .lower_bound(...),因为这样的复杂度是对的(\(\log\)),否则就是线性的。我在cpprefernce上没有翻到非常有用的资料,用duck做了个bench。结果如下:

code 1:

# include <bits/stdc++.h>

std::mt19937 mrand(std::chrono::steady_clock::now().time_since_epoch().count());

uint32_t rnd(uint32_t L, uint32_t R){return mrand() % (R - L + 1) + L; }

constexpr int N = 5e5;

# define ALL(x) x.begin(), x.end()

uint32_t A[N];

signed main() {
	std::set<int> S;
	for (uint32_t i = 1; i <= N; i++)
		S.insert(mrand());
	uint32_t kth;
	std::cin >> kth;
	assert(kth <= N);
	for (uint32_t i = 0; i < N; i++) {
		auto it = std::lower_bound(ALL(S), mrand());
		if (it == S.end()) A[i] = (uint32_t)(-1);
		else A[i] = *it;
	}
	std::nth_element(A, A + kth, A + N);
	std::cout << A[kth - 1] << "\n";
}

结果:

Submitting ...
Compile OK
Time (ms): 1000
Memory (KiB): 23476
Status: Time Limit Exceeded
>>>>>>> stdout (first 512 bytes) <<<<<<<

>>>>>>> stderr (first 512 bytes) <<<<<<<

========================================

code 2:

# include <bits/stdc++.h>

std::mt19937 mrand(std::chrono::steady_clock::now().time_since_epoch().count());

uint32_t rnd(uint32_t L, uint32_t R){return mrand() % (R - L + 1) + L; }

constexpr int N = 5e5;

# define ALL(x) x.begin(), x.end()

uint32_t A[N];

signed main() {
	std::set<int> S;
	for (uint32_t i = 1; i <= N; i++)
		S.insert(mrand());
	uint32_t kth;
	std::cin >> kth;
	assert(kth <= N);
	for (uint32_t i = 0; i < N; i++) {
		auto it = S.lower_bound(mrand());
		if (it == S.end()) A[i] = (uint32_t)(-1);
		else A[i] = *it;
	}
	std::nth_element(A, A + kth, A + N);
	std::cout << A[kth - 1] << "\n";
}

结果:

Submitting ...
Compile OK
Time (ms): 483.526877
Memory (KiB): 25428
Status: Run Finished
>>>>>>> stdout (first 512 bytes) <<<<<<<
3293214969

>>>>>>> stderr (first 512 bytes) <<<<<<<

========================================

显然跑得了5e5的那个是log的,另一个不是log的。

string加入相关

这个是同学在写题的时候写出来问题然后反应过来的。

他需要动态的将一个char放到string后面

他的写法是:

string s; char c;
s = s + c;

这一看是不是没有问题,我们在正常写加减法运算的时候就会习惯性的这么写(有些人喜欢这么写,不包括我)。我去翻了一下cppreference,发现+一个char的操作是给s进行push_back操作,然后在复制过去,就不是\(\mathcal{O(1)}\)的了。而是\(\mathcal{O(size_{S})}\)的。但是push_back\(\mathcal{O(1)}\)的。

具体的在这儿

posted @ 2024-11-18 19:38  georegyucjr  阅读(39)  评论(0)    收藏  举报