【集训队互测2015】最大异或和
生活随笔
收集整理的這篇文章主要介紹了
【集训队互测2015】最大异或和
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
首先不知道有沒有神仙線段樹分治過的。
首先一個較為顯然的性質(zhì):
\[ \mathrm{Span}\{v_1, v_2, \dots, v_n\} = \mathrm{Span}\{v_1, v_2 - v_1, \dots, v_n - v_{n - 1}\} \]
這個啟發(fā)我們維護(hù)差分序列,此時1操作變成了單點異或,2操作變成了單點異或以及區(qū)間清空。
但是這道題維護(hù)的是線性基,所以要用帶刪除的線性基實現(xiàn)。(具體見【集訓(xùn)隊作業(yè)2018】圍繞著我們的圓環(huán))
此時單點異或顯然可以變成插入再刪除。因為線性基的時間復(fù)雜度,此時暴力清空也沒問題。
因為每次操作最多使兩個位置非負(fù),暴力清空時特判空向量,此時可以攤還分析,復(fù)雜度正確。
因此復(fù)雜度為 \(O(\frac{(n+m)mQ}{\omega})\)。
這次優(yōu)化了帶刪除線性基的代碼(從虞大那里參考了部分寫法)
#include <bits/stdc++.h>const int MAXN = 2048; typedef std::bitset<MAXN> B; int n, m, Q; B frm[MAXN], A[MAXN], arr[MAXN]; int bse[MAXN], isb[MAXN]; B read() {static B t; t.reset();static char buf[MAXN]; std::cin >> buf;for (int i = 1; i <= m; ++i) if (buf[i - 1] & 1) t.set(m - i + 1);return t; } void insert(int at) {for (int i = m; i; --i) if (A[at].test(i)) {if (bse[i]) A[at] ^= A[bse[i]], frm[at] ^= frm[bse[i]];else { isb[bse[i] = at] = i; break; }} } void modify(int at, B v) {if (v.none()) return ;int ax = 0; isb[0] = 2001;for (int i = 1; i <= n; ++i)if (frm[i].test(at))isb[i] < isb[ax] ? ax = i : 0;for (int i = 1; i <= n; ++i)if (i != ax && frm[i].test(at))A[i] ^= A[ax], frm[i] ^= frm[ax];if (isb[ax]) bse[isb[ax]] = 0, isb[ax] = 0;A[ax] ^= v, insert(ax); } void output(const B & x) {static char buf[MAXN];for (int i = 1; i <= m; ++i) buf[i - 1] = x[m - i + 1] + '0';std::cout << buf << std::endl; } B query() {static B t; t.reset();for (int i = m; i; --i)if (!t.test(i) && bse[i])t ^= A[bse[i]];return t; } int main() {std::ios_base::sync_with_stdio(false), std::cin.tie(0);std::cin >> n >> m >> Q;B t;for (int i = 1; i <= n; ++i)A[i] = (arr[i] = read()) ^ arr[i - 1], frm[i].set(i), insert(i);while (Q --> 0) {int opt, t1, t2;std::cin >> opt;if (opt == 1) {std::cin >> t1 >> t2; t = read();modify(t1, t);if (t2 < n) modify(t2 + 1, t);for (int i = t1; i <= t2; ++i) arr[i] ^= t;} else if (opt == 2) {std::cin >> t1 >> t2; t = read();modify(t1, arr[t1] ^ t);if (t2 < n) modify(t2 + 1, arr[t2] ^ t);for (int i = t1 + 1; i <= t2; ++i)modify(i, arr[i] ^ arr[i - 1]);for (int i = t1; i <= t2; ++i) arr[i] = t;} else if (opt == 3) output(query());}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/daklqw/p/11545965.html
總結(jié)
以上是生活随笔為你收集整理的【集训队互测2015】最大异或和的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gstreamer开发日志
- 下一篇: 后盾网lavarel视频项目---图片上