如何优雅的使用 stl
啥背景,杀乌鸡
``` Viumbe vyote vya mungu wetu na mfalme wetu Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti Pazeni sauti Viumbe vyote vya mungu wetu na mfalme wetu Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Viumbe vyote vya mungu wetu na mfalme wetu Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti Pazeni sauti Pazeni sauti ili nasi mwimbe Pazeni Pazeni Pazeni PazeniPazeni Pazeni Viumbe vyote vya mungu wetu na mfalme wetu Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti ili nasi mwimbe Pazeni sauti Pazeni sauti Pazeni sauti ili nasi mwimbePazeni sauti Pazeni sauti Pazeni sauti Pazeni sauti ```众所周知的,priority_queue 可以通过一下方式传 lambda 比较函数。
auto Cmp = [](int a, int b){return a > b;};
priority_queue<int, vector<int>, decltype(Cmp)> que(Cmp);
有没有不定义 Cmp
的办法呢?
我们用
#include <cxxabi.h>
cout << abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr) << endl;
输出一下 decltype(Cmp)
到底是什么类型,它其实是一个 lambda 的类型,根本没法输出。
我们翻找 priority_queue
的原理,容易发现其调用了一个构造函数
priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()): c(std::move(__s)), comp(__x){ std::make_heap(c.begin(), c.end(), comp); }
所以它内置了一个比较对象,而我们传入的第三个参就是其类型,我们可以通过构造函数来初始化这个对象。
于是我们用 function
替换掉 decltype
即可:
priority_queue<int, vector<int>, function<bool(int, int)>> que([](int a, int b){return a > b;});
事实上,我们可以自己写一个类似的东西,形如:
template <class T>
class A{T f;A() = default;A(auto k) : f(k){}
};
注意在 C++20 以前 lambda/function 是不能作为值传入 template
的。
当然你也可以用昨天鲜花的内容转成函数指针来传入。
众所周知,可以用 #define protected private
访问 queue
或 stack
的底层结构,类似:
#define protected public
#include <stack>
#include <queue>
#undef protectedqueue<int> que;
for(int i = 1; i <= 10; ++i)que.emplace(i);
for(int i = 9; ~i; --i)cout << que.c[i] << ' ';
这个其实可以扩展。
对于 priority_queue
,我们类似做
#define protected public
#include <stack>
#include <queue>
#undef protectedpriority_queue<int> que;
for(int i = 1; i <= 10; ++i)que.emplace(i);
for(int i = 9; ~i; --i)cout << que.c[i] << ' ';
发现并不是有序的。
这是因为其内部是通过 make_heap
实现的,详细了解可以直接搜,这里说一下如何让他有序。
用 sort_heap(que.c.begin(), que.c.end(), less<int>())
,less<int>()
是 que
的比较函数,注意这里是倒序的。
想还原可以用 make_heap(que.c.begin(), que.c.end(), less<int>())
对于 bitset
,我们也可以直接访问,形如:
#define private public
#include <bitset>
#undef privatebitset<10000> s;
s._M_w[i];
默认是用 long
压的,一般是 \(64\),注意就是这个是 private
,并且是 ._M_w[]
。
这样其实就解决了必须手写 bitset 的一个方面。
给出 P11831 [省选联考 2025] 追忆 的代码。甚至比我手写快
Code
/* Local File
in_out/in.in
in_out/out.out
*/
#define private public
#include <bitset>
#undef private
#include <bits/stdc++.h>
using namespace std;
using llt = long long;
using ull = unsigned long long;
using llf = long double;
#define endl '\n'const int N = 1e5 + 3, W = 64, D = N / W + 1, B = 600, S = N / B + 3;
int n, m, q, va[N], vb[N], pa[N], pb[N];bitset<N> sn[N], ca[S], cb[S];
int bln, id[N], bl[N], br[N];struct Gph{vector<int> to[N];void Add(int u, int v){to[u].emplace_back(v);}void ADD(int u, int v){Add(u, v), Add(v, u);}void Clr(){for(int i = 1; i <= n; ++i)to[i].clear();}
#define For_to(u, v, g) for(auto v : g.to[u])
} g, rg;int rd[N];
void Solve(){cin >> n >> m >> q;for(int i = 1; i <= m; ++i){int u, v; cin >> u >> v;g.Add(u, v), ++rd[u], rg.Add(v, u);}for(int i = 1; i <= n; ++i)cin >> va[i], pa[va[i]] = i;for(int i = 1; i <= n; ++i)cin >> vb[i], pb[vb[i]] = i;queue<int> que;for(int i = 1; i <= n; ++i) if(!rd[i])que.emplace(i);while(!que.empty()){int u = que.front(); que.pop();sn[u][u] = 1;For_to(u, v, g) sn[u] |= sn[v];For_to(u, v, rg)if(!--rd[v]) que.emplace(v);}bln = 0;for(int l = 1; l <= n; l += B){++bln;for(int j = bl[bln] = l, r = br[bln] = min(l + B - 1, n); j <= r; ++j)ca[bln][pa[j]] = 1, cb[bln][pb[j]] = 1, id[j] = bln;}for(int i = bln - 1; i; --i)ca[i] |= ca[i + 1], cb[i] |= cb[i + 1];for(int tst = 1; tst <= q; ++tst){int op; cin >> op;if(op == 1){int x, y; cin >> x >> y;int ix = id[va[x]], iy = id[va[y]];swap(va[x], va[y]), pa[va[x]] = x, pa[va[y]] = y;for(int i = 1; i <= ix; ++i) ca[i][x] = 0;for(int i = 1; i <= iy; ++i) ca[i][x] = 1;for(int i = 1; i <= iy; ++i) ca[i][y] = 0;for(int i = 1; i <= ix; ++i) ca[i][y] = 1;}else if(op == 2){int x, y; cin >> x >> y;int ix = id[vb[x]], iy = id[vb[y]];swap(vb[x], vb[y]), pb[vb[x]] = x, pb[vb[y]] = y;for(int i = 1; i <= ix; ++i) cb[i][x] = 0;for(int i = 1; i <= iy; ++i) cb[i][x] = 1;for(int i = 1; i <= iy; ++i) cb[i][y] = 0;for(int i = 1; i <= ix; ++i) cb[i][y] = 1;}else{int u, l, r; cin >> u >> l >> r;int il = id[l], ir = id[r];bitset<N> k(ca[il] ^ ca[ir]);for(int i = bl[ir]; i <= r; ++i) k[pa[i]] = 1;for(int i = bl[il]; i < l; ++i) k[pa[i]] = 0;k &= sn[u];int p = 0;for(int i = 0; i < D; ++i)while(p < bln && (cb[p + 1]._M_w[i] & k._M_w[i])) ++p;if(!p) cout << 0 << endl;elsefor(int i = br[p]; i >= bl[p]; --i){int p = pb[i];if(k[p]){cout << i << endl;break;}}}}
}void Clear(){memset(sn, 0, sizeof sn);memset(ca, 0, sizeof ca);memset(cb, 0, sizeof cb);g.Clr(), rg.Clr();
}int main(){ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);int c, t; cin >> c >> t;while(t--) Solve(), Clear();
}
众所周知,在 tr2/dynamic_bitset
头文件中有一个 dynamic_bitset
,其支持动态 resize
。
具体可以看 dynamic_bitset。
但是众所不周知,其 is_subset_of
(话说这个 subset
竟然是后缀)写挂了……
所以你直接用 is_subset_of
会 CE。
5k 曾给出过:
#define is_proper_subset_of is_subset_of(const dynamic_bitset& __b)\{ return this->_M_is_subset_of(__b); }\bool qwq
我们分析一下原因。
翻找源码:
bool _M_is_subset_of(const __dynamic_bitset_base& __b) noexcept{if (__b._M_w.size() == this->_M_w.size()){for (size_t __i = 0; __i < this->_M_w.size(); ++__i)if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i]))return false;return true;}else return false;
}bool is_subset_of(const dynamic_bitset& __b) const{ return this->_M_is_subset_of(__b); }
容易发现其问题:在 bool _M_is_subset_of(const __dynamic_bitset_base& __b)
后少了一个 const
。
写源代码不编译的人这辈子有了。
但是我们不太能直接加上一个 const
,于是我们曲线救国,把 is_proper_subset_of
define
成一个新的 is_subset_of
即可。
这样就不能用 is_proper_subset_of
了(当然也不能用 qwq
做变量名),但事实上是 is_proper_subset_of
的源码更绝望,其有好多错特别不好改,还是用 is_subset_of && !=
替代吧。
其实要是只是想用的话有更简单的方式,我们发现 is_subset_of
本质上就是调用了一个 _M_is_subset_of
,并且 dynamic_bitset
和 __dynamic_bitset_base
之间可直接转换,所以如下即可:
#define private public
#include <tr2/dynamic_bitset>
#undef privatetr2::dynamic_bitset<> a, b;
a._M_is_subset_of(b);
P