线段树测试
线段树所思所记
线段树是一种 维护区间信息 的数据结构,在 \(O(log\ n)\) 的时间复杂度内实现 单点修改、区间修改、单点查询,区间查询(区间求和,求区间最大值,求区间最小值) 等操作。
-
代码
#include<iostream> using namespace std; namespace SegmentTree { static unsigned lim; static unsigned* a; using cints = const unsigned&; constexpr unsigned maxn = 1e5; enum class ArrayState { UnSet, AllZero, AllOne }; struct node { struct son { static inline unsigned lft(cints root) { return root << 1; } static inline unsigned rit(cints root) { return root << 1 | 1; } }; struct tags { template<node* seg> static inline void pushdown(cints root, cints l, cints r) { if (seg[root].tag.state == ArrayState::UnSet) return; const auto lc = son::lft(root), rc = son::rit(root), mid = midof(l,r); seg[lc].tag.state = seg[rc].tag.state = seg[root].tag.state; if (seg[root].tag.state == ArrayState::AllOne) { seg[lc].val.cnt = mid - l + 1; seg[rc].val.cnt = r - mid; } else seg[lc].val.cnt = seg[rc].val.cnt = 0; seg[root].tag.state = ArrayState::UnSet; } ArrayState state; }tag; struct vals { unsigned cnt; template<node* seg> static inline void update(cints root) { seg[root].val.cnt = seg[son::lft(root)].val.cnt + seg[son::rit(root)].val.cnt; } }val; static inline void tie(unsigned* Arr) { a = Arr; } static inline const unsigned midof(cints l, cints r) { return ((r - l) >> 1) + l; } template<node* seg> static void build(cints root, cints l, cints r) { if (l == r) return void(seg[root].val.cnt = (a[l] >= lim)); node::build<seg>(son::lft(root), l, midof(l, r)), node::build<seg>(son::rit(root), midof(l, r) + 1, r); vals::update<seg>(root); seg[root].tag.state = ArrayState::UnSet; } struct gets { template<node* seg> static unsigned cntof(cints root, cints ml, cints mr, cints ql, cints qr) { if (ql <= ml && mr <= qr) return seg[root].val.cnt; if (ql > mr || qr < ml) return 0; tags::pushdown<seg>(root, ml, mr); return gets::cntof<seg>(son::lft(root), ml, midof(ml, mr), ql, qr) + gets::cntof<seg>(son::rit(root), midof(ml, mr) + 1, mr, ql, qr); } template<node* seg> static const vals pointof(cints root, cints l, cints r, cints on){ if (l == on && r == on) return seg[root].val; tags::pushdown<seg>(root, l, r); if (auto mid = midof(l, r); on <= mid) return gets::pointof<seg>(son::lft(root), l, mid, on); else return gets::pointof<seg>(son::rit(root), mid + 1, r, on); } }; struct update { template<node* seg> static inline void sets(cints root, cints ml, cints mr, cints ql, cints qr, cints val){ if (ql <= ml && qr >= mr) return void(seg[root].val.cnt = val * (mr - ml + 1)), void(seg[root].tag.state = (val ? ArrayState::AllOne : ArrayState::AllZero)); if (ql > mr || qr < ml) return; tags::pushdown<seg>(root, ml, mr); update::sets<seg>(son::lft(root), ml, midof(ml,mr), ql, qr, val); update::sets<seg>(son::rit(root), midof(ml, mr) + 1, mr, ql, qr, val); vals::update<seg>(root); } }; } nnd[maxn]; } unsigned a[SegmentTree::maxn],L[SegmentTree::maxn],R[SegmentTree::maxn],p,n,m; char opt[SegmentTree::maxn]; template<SegmentTree::node* seg> inline const bool check(const unsigned int& x){ SegmentTree::lim = x; SegmentTree::node::build<seg>(1, 1, n); for (unsigned i = 1; i <= m; ++i) if (unsigned cnt1 = SegmentTree::node::gets::cntof<seg>(1, 1, n, L[i], R[i]);opt[i] == '0') SegmentTree::node::update::sets<seg>(1, 1, n, R[i] - cnt1 + 1, R[i], 1), SegmentTree::node::update::sets<seg>(1, 1, n, L[i], R[i] - cnt1, 0); else SegmentTree::node::update::sets<seg>(1, 1, n, L[i], L[i] + cnt1 - 1, 1), SegmentTree::node::update::sets<seg>(1, 1, n, L[i] + cnt1, R[i], 0); return SegmentTree::node::gets::pointof<seg>(1, 1, n, p).cnt; } int main() { ios::sync_with_stdio(0), cin.tie(0), std::cout.tie(0); cin >> n >> m; for (int i = 1; i <= n; i++) cin>>a[i]; SegmentTree::node::tie(a); for (int i = 1; i <= m; i++) { cin>>opt[i]>>L[i]>>R[i]; } cin>>p; int ll = 1, rr = n, midd, ans=0; while (ll <= rr) if(midd = (ll + rr) >> 1;check<SegmentTree::nnd>(midd)) ans = midd, ll = midd + 1; else rr = midd - 1; std::cout << ans; return 0; }
-
铺垫
因为线段树特性,定义了
struct son
。static unsigned lim; static unsigned* a; using cints = const unsigned&; constexpr unsigned maxn = 1e5; enum class ArrayState { UnSet, AllZero, AllOne }; struct node { struct son { static inline unsigned lft(cints root) { return root << 1; } static inline unsigned rit(cints root) { return root << 1 | 1; } }; }
-
构建