structtrie { trie *son[26]; trie() { for (int i = 0; i < 26; i++) son[i] = NULL; tag = 0; } bool tag; };
trie *root = new trie; int n, m; string s;
voidinsert(conststring &s){ trie *cur = root; for (int i = 0; i < s.size(); i++) { int temp = s[i] - 'a'; if (cur->son[temp] == NULL) cur->son[temp] = new trie; cur = cur->son[temp]; } }
intsearch(conststring &s){ trie *cur = root; for (int i = 0; i < s.size(); i++) { int temp = s[i] - 'a'; if (cur->son[temp] == NULL) return0; cur = cur->son[temp]; if (i == s.size() - 1) { if (!cur->tag) return cur->tag = 1, 1; else return2; } } }
intmain(){ cin >> n; while (n--) cin >> s, insert(s); cin >> m; while (m--) { cin >> s; int now = search(s); if (now == 0) cout << "WRONG" << endl; elseif (now == 1) cout << "OK" << endl; else cout << "REPEAT" << endl; } return0; }
structtrie { trie *son[10]; trie() { for (int i = 0; i < 10; i++) son[i] = NULL; visTag = isEnd = 0; } bool visTag, isEnd; } * root;
int n, T; bool ans; string s;
voidinsert(conststring &s){ trie *cur = root; for (int i = 0; i < s.size(); i++) { int temp = s[i] - '0'; if (cur->son[temp] == NULL) cur->son[temp] = new trie; cur = cur->son[temp]; if (cur->isEnd) { ans = 0; break; } if (i == s.size() - 1) { cur->isEnd = 1; if (cur->visTag) ans = 0; } cur->visTag = 1; } }
voidtrie_delete(trie *cur){ for (int i = 0; i < 10; i++) if (cur->son[i]) trie_delete(cur->son[i]); delete cur; }
intmain(){ cin >> T; while (T--) { root = new trie; ans = 1; cin >> n; for (int i = 1; i <= n; i++) cin >> s, insert(s); puts(ans ? "YES" : "NO"); trie_delete(root); } return0; }
ll read(){ char ch = getchar(); ll x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(ll val){ staticint tot; int cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (trie[cur].son[now] == -1) trie[cur].son[now] = ++tot; cur = trie[cur].son[now]; } }
voidquery(ll val){ int cur = root; ll ans = 0; for (int i = BIT; ~i; i--) { ll now = (val >> i) & 1; if (trie[cur].son[now ^ 1] != -1) ans |= (now ^ 1) << i, cur = trie[cur].son[now ^ 1]; else ans |= now << i, cur = trie[cur].son[now]; } printf("%lld\n", ans); }
intmain(){ n = read(), m = read(); for (int i = 1; i <= n; i++) insert(read()); for (int i = 1; i <= m; i++) query(read()); return0; }
structtrie { int son[2]; int cnt; trie() { son[0] = son[1] = -1; cnt = 0; } } trie[1001 * (BIT + 1)]; int root = 0;
intread(){ char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(int val){ staticint tot; int cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (trie[cur].son[now] == -1) trie[cur].son[now] = ++tot; cur = trie[cur].son[now]; trie[cur].cnt++; } }
voidtrie_delete(int val){ int cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; cur = trie[cur].son[now]; trie[cur].cnt--; } }
voidtrie_add(int val){ int cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; cur = trie[cur].son[now]; trie[cur].cnt++; } }
voidquery(int val, int x, int y){ trie_delete(a[x]), trie_delete(a[y]); int cur = root; int ans = 0; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (trie[cur].son[now ^ 1] != -1 && trie[trie[cur].son[now ^ 1]].cnt) ans |= 1 << i, cur = trie[cur].son[now ^ 1]; elseif (trie[trie[cur].son[now]].cnt) cur = trie[cur].son[now]; else return; } trie_add(a[x]), trie_add(a[y]); mx = max(mx, ans); }
intmain(){ n = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i <= n; i++) insert(a[i]); for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) query(a[i] + a[j], i, j); cout << mx; return0; }
typedeflonglong ll; constint BIT = 31; constint maxn = 400005; int n, a[maxn], tot; ll preXor = 0, posXor = 0, preMx[maxn], posMx[maxn]; ll ans = 0;
structtrie { int son[2]; trie() { son[0] = son[1] = -1; } } trie[maxn * BIT * 2]; int root;
intread(){ char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(ll val){ int cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (trie[cur].son[now] == -1) trie[cur].son[now] = ++tot; cur = trie[cur].son[now]; } }
ll query(ll val){ int cur = root; ll ans = 0; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (trie[cur].son[now ^ 1] != -1) ans |= 1ll << i, cur = trie[cur].son[now ^ 1]; else cur = trie[cur].son[now]; } return ans; }
intmain(){ n = read(); for (int i = 1; i <= n; i++) a[i] = read();
insert(0); for (int i = 1; i <= n; i++) { preXor ^= a[i]; insert(preXor); preMx[i] = max(preMx[i - 1], query(preXor)); } for (int i = 0; i <= tot; i++) trie[i].son[0] = trie[i].son[1] = -1; tot = 0;
insert(0); for (int i = n; i >= 1; i--) { posXor ^= a[i]; insert(posXor); posMx[i] = max(posMx[i + 1], query(posXor)); } for (int i = 1; i <= n - 1; i++) ans = max(ans, posMx[i + 1] + preMx[i]); cout << ans; return0; }
template <classT> voidread(T &x, intf = 1) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
voidadd(int from, int to, int val){ staticint t; e[t].to = to, e[t].val = val, e[t].nxt = p[from], p[from] = t++; }
voiddfs(int now, int val){ XOR[now] = val, vis[now] = 1; for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (!vis[to]) dfs(to, val ^ e[i].val); } }
voidinsert(int val){ trie *cur = root; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (cur->son[now] == NULL) cur->son[now] = new trie; cur = cur->son[now]; } }
intquery(int val){ trie *cur = root; int ans = 0; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (cur->son[now ^ 1] != NULL) ans |= 1 << i, cur = cur->son[now ^ 1]; else cur = cur->son[now]; } return ans; }
intmain(){ memset(p, -1, sizeof(p)); read(n); for (int i = 1; i <= n - 1; i++) { read(u), read(v), read(w); add(u, v, w), add(v, u, w); } dfs(1, 0); root = new trie; for (int i = 1; i <= n; i++) insert(XOR[i]); for (int i = 1; i <= n; i++) ans = max(ans, query(XOR[i])); cout << ans; return0; }
template <classT> voidread(T& x, intf = 1) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
voidinsert(vector<bool>& bin){ trie* cur = root; for (int i = 0; i < bin.size(); i++) { int now = bin[i]; if (cur->son[now] == NULL) cur->son[now] = new trie; cur = cur->son[now]; cur->sum++; } cur->cntEnd++; }
intquery(vector<bool>& bin){ trie* cur = root; int ans = 0; for (int i = 0; i < bin.size(); i++) { int now = bin[i]; if (cur->son[now] == NULL) return ans; cur = cur->son[now]; ans += cur->cntEnd; } ans += cur->sum - cur->cntEnd; return ans; }
intmain(){ read(m), read(n); root = new trie; for (int i = 1; i <= m; i++) { read(k); vector<bool> bin; for (int i = 1; i <= k; i++) read(v), bin.push_back(v); insert(bin); } for (int i = 1; i <= n; i++) { read(k); vector<bool> bin; for (int i = 1; i <= k; i++) read(v), bin.push_back(v); cout << query(bin) << endl; } return0; }
int n; char s[21]; vector<char> ans; structtrie { int son[26]; bool isEnd, tag; trie() { for (int i = 0; i < 26; i++) son[i] = -1; isEnd = tag = 0; } } trie[25000 * 20]; int root, tot;
voidinsert(conststring& s){ int cur = root; for (int i = 0; i < s.size(); i++) { int now = s[i] - 'a'; if (trie[cur].son[now] == -1) trie[cur].son[now] = ++tot; cur = trie[cur].son[now]; } trie[cur].isEnd = 1; }
voidaddTag(conststring& s){ int cur = root; for (int i = 0; i < s.size(); i++) { cur = trie[cur].son[s[i] - 'a']; trie[cur].tag = 1; } }
voiddfs(int now){ int last = -1; for (int i = 0; i < 26; i++) { if (trie[now].son[i] != -1) { if (!trie[trie[now].son[i]].tag) { ans.push_back(i + 'a'); if (trie[trie[now].son[i]].isEnd) ans.push_back('P'); dfs(trie[now].son[i]); ans.push_back('-'); } else last = i; } } if (last != -1) { ans.push_back(last + 'a'); if (trie[trie[now].son[last]].isEnd) ans.push_back('P'); dfs(trie[now].son[last]); } }
intmain(){ scanf("%d", &n); int mxLen = 0; string lastString; for (int i = 1; i <= n; i++) { scanf("%s", s); if (strlen(s) > mxLen) mxLen = strlen(s), lastString = s; insert(s); } addTag(lastString); dfs(root); printf("%d\n", ans.size()); for (int i = 0; i < ans.size(); i++) putchar(ans[i]), putchar('\n'); return0; }
constint maxn = 30005; int n, ans; string s[maxn]; int inDegree[26]; vector<int> v[26]; vector<int> firstId;
structtrie { trie* son[26]; bool isEnd; trie() { for (int i = 0; i < 26; i++) son[i] = NULL; isEnd = 0; } } * root;
voidinsert(conststring& s){ trie* cur = root; for (int i = 0; i < s.size(); i++) { if (cur->son[s[i] - 'a'] == NULL) cur->son[s[i] - 'a'] = new trie; if (i == s.size() - 1) cur->son[s[i] - 'a']->isEnd = 1; cur = cur->son[s[i] - 'a']; } }
boolcheck(conststring& s){ for (int i = 0; i < 26; i++) { v[i].clear(); inDegree[i] = 0; } trie* cur = root; for (int i = 0; i < s.size(); i++) { for (int j = 0; j < 26; j++) if (cur->son[j] != NULL && j != s[i] - 'a') { v[s[i] - 'a'].push_back(j); inDegree[j]++; } if (i != s.size() - 1 && cur->son[s[i] - 'a']->isEnd) returnfalse; cur = cur->son[s[i] - 'a']; } stack<int> st; for (int i = 0; i < 26; i++) if (!inDegree[i]) st.push(i); while (!st.empty()) { int now = st.top(); st.pop(); for (int i = 0; i < v[now].size(); i++) { inDegree[v[now][i]]--; if (!inDegree[v[now][i]]) st.push(v[now][i]); } } for (int i = 0; i < 26; i++) if (inDegree[i]) returnfalse; returntrue; }
intmain(){ ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n; root = new trie; for (int i = 1; i <= n; i++) cin >> s[i], insert(s[i]); for (int i = 1; i <= n; i++) if (check(s[i])) firstId.push_back(i), ans++; cout << ans << endl; for (int i = 0; i < firstId.size(); i++) cout << s[firstId[i]] << endl; return0; }
先把IP地址按题目要求转化为二进制插入 trie 树,顺便对最后访问的节点记录 inTime 和 length, 分别表示这个 IP 地址被插入的时间和掩码长度。查询时,对于 inTime 在 a 和 b 之间的 IP 地址,记录对应掩码长度, 将这两个信息存入 Vector;对于 inTime 在 a 之前的节点,更新掩码长度最大值。最后对 Vector 按照 IP 地址按插入时间排序,然后从前到后扫一遍 Vector,同时更新掩码长度最大值,就可以知道该待查询的IP地址的路由表项选择发生了多少次变化。
int n, x, cntAdd, len, a, b; char type; structtrie { trie* son[2]; int inTime, length; trie() { son[1] = son[0] = NULL; inTime = length = 0; } } * root;
intread(){ char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(vector<bool>& bin, int l, int id){ trie* cur = root; for (int i = 0; i < l; i++) { int now = bin[i]; if (cur->son[now] == NULL) cur->son[now] = new trie; cur = cur->son[now]; if (i == l - 1) { cur->inTime = id; cur->length = l; } } }
voidquery(vector<bool>& bin, int l, int r){ trie* cur = root; int cnt = 0, mx = 0; vector<pii> tmp; for (int i = 0; i < bin.size(); i++) { int now = bin[i]; if (cur->son[now] == NULL) break; cur = cur->son[now]; if (cur->inTime >= l && cur->inTime <= r) tmp.push_back(make_pair(cur->inTime, cur->length)); elseif (cur->inTime < l) mx = max(mx, cur->length); } sort(tmp.begin(), tmp.end()); for (int i = 0; i < tmp.size(); i++) if (tmp[i].second > mx) mx = tmp[i].second, cnt++; printf("%d\n", cnt); }
intmain(){ n = read(); root = new trie; for (int i = 1; i <= n; i++) { type = getchar(); if (type == 'A') { cntAdd++; vector<bool> bin; for (int i = 1; i <= 4; i++) { x = read(); for (int j = 7; ~j; j--) bin.push_back((x >> j) & 1); } len = read(); insert(bin, len, cntAdd); } else { vector<bool> bin; for (int i = 1; i <= 4; i++) { x = read(); for (int j = 7; ~j; j--) bin.push_back((x >> j) & 1); } a = read(), b = read(); query(bin, a, b); } } return0; }
int n, m, ans, tot; string s; structtrie { trie* son[26]; int endTag; trie() { for (int i = 0; i < 26; i++) son[i] = NULL; endTag = 0; } } * root; unordered_map<int, bool> vis;
voidinsert(conststring& s, int id){ trie* cur = root; for (int i = 0; i < s.size(); i++) { if (cur->son[s[i] - 'a'] == NULL) cur->son[s[i] - 'a'] = new trie; cur = cur->son[s[i] - 'a']; } cur->endTag = id; }
boolisWord(conststring& s){ trie* cur = root; for (int i = 0; i < s.size(); i++) { if (cur->son[s[i] - 'a'] == NULL) returnfalse; cur = cur->son[s[i] - 'a']; if (i == s.size() - 1 && cur->endTag) returntrue; } returnfalse; }
voiddfs(trie* now, int i, bool canOpt){ if (i == s.size()) { if (now->endTag && !vis[now->endTag]) ans++, vis[now->endTag] = 1; if (canOpt) { for (int k = 0; k < 26; k++) if (now->son[k] != NULL && now->son[k]->endTag && !vis[now->son[k]->endTag]) ans++, vis[now->son[k]->endTag] = 1; } return; } if (!canOpt && now->son[s[i] - 'a'] == NULL) return; if (now->son[s[i] - 'a'] != NULL) dfs(now->son[s[i] - 'a'], i + 1, canOpt); if (canOpt) { //增加一位 for (int k = 0; k < 26; k++) if (now->son[k] != NULL) dfs(now->son[k], i, 0); //删除一位 dfs(now, i + 1, 0); //修改一位 for (int k = 0; k < 26; k++) if (now->son[k] != NULL) dfs(now->son[k], i + 1, 0); } }
intmain(){ ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> m; root = new trie; for (int i = 1; i <= n; i++) { cin >> s; insert(s, i); } for (int i = 1; i <= m; i++) { vis.clear(); cin >> s; if (isWord(s)) cout << -1 << endl; else { ans = 0; dfs(root, 0, 1); cout << ans << endl; } } return0; }
constint maxn = 505; int n, ans, len; char s[maxn], T[maxn * 2]; int isVirus[maxn], firstId[maxn]; int to[200]; bitset<1001> vis[maxn * maxn];
structtrie { trie* son[4]; int endTag, num; trie() { for (int i = 0; i < 4; i++) son[i] = NULL; endTag = num = 0; } } * root;
voidinsert(conststring& s, constint& id){ staticint tot; trie* cur = root; for (int i = 0; i < s.size(); i++) { if (cur->son[to[s[i]]] == NULL) cur->son[to[s[i]]] = new trie; cur = cur->son[to[s[i]]]; cur->num = ++tot; } if (!cur->endTag) cur->endTag = id; firstId[id] = cur->endTag; }
voidmatch(trie* now, int i){ if (i == len) { isVirus[now->endTag] = 1; return; } if (vis[now->num][i]) return; vis[now->num][i] = 1; if (T[i] == '*') { match(now, i + 1); for (int k = 0; k < 4; k++) if (now->son[k] != NULL) match(now->son[k], i + 1), match(now->son[k], i); } elseif (T[i] == '?') { for (int k = 0; k < 4; k++) if (now->son[k] != NULL) match(now->son[k], i + 1); } else { if (now->son[to[T[i]]] != NULL) match(now->son[to[T[i]]], i + 1); } }
intmain(){ to['A'] = 0, to['T'] = 1, to['C'] = 2, to['G'] = 3; scanf("%s%d", T, &n); len = strlen(T); root = new trie; for (int i = 1; i <= n; i++) scanf("%s", s), insert(s, i); for (int i = 0; i < maxn * maxn; i++) vis[i].reset(); match(root, 0); for (int i = 1; i <= n; i++) if (isVirus[firstId[i]]) ans++; printf("%d\n", n - ans); return0; }
先证明按 dfs 序选取一定最优,对于以同一深度的节点为根的一系列子树,在一颗中找一个叶子节点 j,在另一颗里找一个根节点 i (当前序列中j所在的子树的根在i之前出现)。需要明确的是,只有这两种节点间才能交换顺序,否则得到序列不满足情形 3 。假设 j 在 i 之前代价最小,尝试将 j 放在 i 的后面。可以发现发现 i 的孩子们和 i 的距离都会加 1,所以总代价会增加,而 j 和 j 的父亲的距离一定也会增加,所以总代价也会增加。
constint maxn = 510005; int n, sz[maxn], in[maxn]; string s; ll ans; vector<int> v[maxn];
structtrie { int son[26]; int tag; trie() { for (int i = 0; i < 26; i++) son[i] = -1; tag = 0; } } trie[maxn]; int root, tot;
voidinsert(conststring &s){ int cur = root; for (int i = s.size() - 1; ~i; i--) { int now = s[i] - 'a'; if (trie[cur].son[now] == -1) trie[cur].son[now] = ++tot; cur = trie[cur].son[now]; if (!i) trie[cur].tag = 1; } }
voidrebuild(int now, int pre){ for (int i = 0; i < 26; i++) { if (trie[now].son[i] != -1) { if (trie[trie[now].son[i]].tag) { v[pre].push_back(trie[now].son[i]); rebuild(trie[now].son[i], trie[now].son[i]); } else rebuild(trie[now].son[i], pre); } } }
constint maxn = 100005; int n, m, pos[50]; // pos[k]对应最大左端点,使得 data(pos[k],i)=k; //大于pos[k]的位置,data(pos[k],i)<k char s[maxn]; ll ans[maxn]; structtrie { trie* son[2]; int last; trie() { son[0] = son[1] = NULL; last = 0; } } * root;
structQuestion { int l, r, qId; booloperator<(const Question& other) { return r < other.r; } } Q[maxn];
intread(){ char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(int st){ trie* cur = root; for (int i = st; i <= min(st + 39, n); i++) { int now = s[i] - '0'; if (cur->son[now] == NULL) cur->son[now] = new trie; cur = cur->son[now]; if (cur->last) pos[i - st + 1] = max(pos[i - st + 1], cur->last); cur->last = st; } }
intmain(){ n = read(), m = read(); scanf("%s", s + 1); for (int i = 1; i <= m; i++) Q[i].l = read(), Q[i].r = read(), Q[i].qId = i; sort(Q + 1, Q + m + 1); root = new trie; for (int i = 1, j = 1; i <= n; i++) { insert(i); //插入起始位置在i的串 while (j <= m && Q[j].r == i) {//以i结尾询问 for (int k = 1; k <= 40; k++) {//枚举长度 if (pos[k] >= Q[j].l)// pos[k]在[l,r]内 ans[Q[j].qId] +=k * (pos[k] - max(pos[k + 1] + 1, Q[j].l) +1); else break; // data(pos[k+1]+1,pos[k])=k //由pos单调性可知更大的k都不合法 } j++; //下一个询问 } } for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]); return0; }
constint maxn = 1e5 + 5; int n, m, type, l, r, X, lastN, lastXor; int a[maxn * 2], sum[maxn * 2][31];
structtrie { trie* son[2]; int sz; int cnt[31]; trie() { son[0] = son[1] = NULL; for (int i = 0; i < 31; i++) cnt[i] = 0; sz = 0; } } * root;
intread(){ char ch = getchar(); int x = 0, f = 1; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); return x * f; }
voidinsert(constint& x){ trie* cur = root; for (int i = 30; i >= 0; i--) { int to = (x >> i) & 1; if (cur->son[to] == NULL) cur->son[to] = new trie; cur = cur->son[to]; cur->sz++; for (int k = 0; k <= 30; ++k) cur->cnt[k] += (x >> k) & 1; } }
ll query2(constint& l, constint& r){ ll ans = 0, len = r - l + 1; for (int i = 0; i < 31; i++) { ll cnt = sum[r][i] - sum[l - 1][i]; if ((X >> i) & 1) cnt = len - cnt; ans += cnt << i; } return ans; }
ll query1(int sz){ if (!sz) return0; ll ans = 0, val = 0; //val 记录排名第sz的数在当前树中的值,最后实际值要异或全局X //ans 在查询的时候已经对X异或过了,最后不需要再异或 trie* cur = root; for (int i = 30; i >= 0; --i) { int to = (lastXor >> i) & 1; //最后一次排序后的异或值 if (cur->son[to] != NULL && sz <= cur->son[to]->sz) cur = cur->son[to], val |= to << i; else { int sizeOfSon = (cur->son[to] == NULL ? 0 : cur->son[to]->sz); //统计son[to]的贡献, 注意用的是当前异或值 for (int k = 0; k < 31; k++) { ll cnt = (cur->son[to] == NULL ? 0 : cur->son[to]->cnt[k]); if ((X >> k) & 1) cnt = sizeOfSon - cnt;//实际值要异或X ans += cnt << k; } //走另外一边 sz -= sizeOfSon; cur = cur->son[to ^ 1]; val |= (to ^ 1) << i; } } return ans + (val ^ X) * sz; //可能多个数结尾在同一链 }
intmain(){ n = read(); for (int i = 1; i <= n; i++) { a[i] = read(); for (int k = 0; k < 31; k++) sum[i][k] = sum[i - 1][k] + ((a[i] >> k) & 1); } m = read(); root = new trie; for (int i = 1; i <= m; i++) { type = read(); if (type == 1) { a[++n] = read() ^ X; for (int k = 0; k < 31; k++) sum[n][k] = sum[n - 1][k] + ((a[n] >> k) & 1); } elseif (type == 2) { l = read(), r = read(); //有序部分用trie处理,无序部分利用前缀和 if (r <= lastN) printf("%lld\n", query1(r) - query1(l - 1)); elseif (l > lastN) printf("%lld\n", query2(l, r)); else printf("%lld\n", query1(lastN) - query1(l - 1) + query2(lastN + 1, r)); } elseif (type == 3) { X ^= read(); } else { for (int k = lastN + 1; k <= n; k++) insert(a[k]); memset(sum[n], 0, sizeof(sum[n])); lastN = n, lastXor = X; } } return0; }
int n, p, l, type; structtrie { trie* son[2]; int sum; trie() { son[0] = son[1] = NULL; sum = 0; } } * root;
template <classT> voidread(T& x, intf = 1) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
voidinsert(int p, int type){ trie* cur = root; for (int i = 31; ~i; i--) { int now = (p >> i) & 1; if (cur->son[now] == NULL) cur->son[now] = new trie; cur = cur->son[now]; cur->sum += type; } }
voidquery(int p, int l){ int ans = 0; trie* cur = root; for (int i = 31; ~i; i--) { bool pi = (p >> i) & 1; bool li = (l >> i) & 1; if (cur == NULL) break; if (li && cur->son[pi] != NULL) ans += cur->son[pi]->sum; cur = cur->son[pi ^ li]; } printf("%d\n", ans); }
intmain(){ read(n); root = new trie; for (int i = 1; i <= n; i++) { read(type), read(p); if (type == 1) insert(p, 1); elseif (type == 2) insert(p, -1); else read(l), query(p, l); } return0; }
voidinitRoot(){ trie *cur = newNode(root[1][0], 0); trie *tmp = newNode(root[1][1], 1); for (int i = BIT; ~i; i--) { int now = (val[1] >> i) & 1; cur = newNode(cur->son[now], 0); tmp = newNode(tmp->son[now], 1); cur->last = tmp->last = 1; } }
voidinsert(trie *pre, trie *cur, int val, int last, bool tag){ for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (pre != NULL) { cur->son[now ^ 1] = pre->son[now ^ 1]; pre = pre->son[now]; } cur = newNode(cur->son[now], tag); cur->last = last; } }
intquery(trie *cur, int val, int last){ int ans = 0; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (cur->son[now ^ 1] != NULL && cur->son[now ^ 1]->last >= last) cur = cur->son[now ^ 1], ans += 1 << i; elseif (cur->son[now] != NULL && cur->son[now]->last >= last) cur = cur->son[now]; else break; } return ans; }
structedge { int to, nxt; } e[MAXN * 2];
voidaddEdge(int from, int to){ staticint t; e[t].to = to, e[t].nxt = p[from], p[from] = t++; }
voiddfs1(constint &now){ staticint times = 1; in[now] = times++; for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (!in[to]) { insert(root[times - 1][0], newNode(root[times][0], 0), val[to], times, 0); dfs1(to); } } out[now] = times; }
voiddfs2(int now, int d){ depth[now] = d; for (int i = p[now]; ~i; i = e[i].nxt) { int to = e[i].to; if (!depth[to]) { fa[to][0] = now; insert(root[now][1], newNode(root[to][1], 1), val[to], d + 1, 1); dfs2(to, d + 1); } } }
voidgetFa(){ for (int j = 1; (1 << j) <= n; j++) for (int i = 1; i <= n; i++) if (fa[i][j - 1]) fa[i][j] = fa[fa[i][j - 1]][j - 1]; }
intlca(int a, int b, int i = 0){ if (depth[a] < depth[b]) swap(a, b); for (; (1 << i) <= depth[a]; i++) ; for (int j = i - 1; j >= 0; j--) if (depth[a] - depth[b] >= (1 << j)) a = fa[a][j]; if (a == b) return a; for (int j = i - 1; j >= 0; j--) if (fa[a][j] && fa[a][j] != fa[b][j]) a = fa[a][j], b = fa[b][j]; return fa[a][0]; }
intmain(){ read(n), read(q); for (int i = 1; i <= n; i++) read(val[i]); memset(p, -1, sizeof(p)); for (int i = 1; i <= n - 1; i++) { read(u), read(v); addEdge(u, v), addEdge(v, u); } initRoot(); dfs1(1); dfs2(1, 1); getFa(); for (int i = 1; i <= q; i++) { read(opt); if (opt == 1) { read(u), read(z); printf("%d\n", query(root[out[u] - 1][0], z, in[u])); } else { read(u), read(v), read(z); int tmp = lca(u, v); printf("%d\n", max(query(root[u][1], z, depth[tmp]), query(root[v][1], z, depth[tmp]))); } } return0; }
usingnamespacestd; constint MAXN = 5e4 + 5; constint BIT = 30; int n, a[MAXN], b[MAXN], l[MAXN][3], r[MAXN][3];
template <classT> voidread(T &x, intf = 1) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : 1), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar(); x *= f; }
structtrie { trie *son[2]; int last; trie() { son[0] = son[1] = NULL; last = 0; } } * root[MAXN];
voidinsert(int id){ trie *cur = root[id] = new trie, *pre = root[id - 1]; for (int i = BIT; ~i; i--) { int now = (a[id] >> i) & 1; if (pre != NULL) { cur->son[now ^ 1] = pre->son[now ^ 1]; pre = pre->son[now]; } cur->son[now] = new trie; cur = cur->son[now]; cur->last = id; } }
intquery(trie *cur, int last, int val){ int ans = 0; for (int i = BIT; ~i; i--) { int now = (val >> i) & 1; if (cur->son[now ^ 1] != NULL && cur->son[now ^ 1]->last >= last) cur = cur->son[now ^ 1], ans |= 1 << i; else cur = cur->son[now]; } return ans; }