首页 > 其他分享 >AtCoder Beginner Contest 308 G Minimum Xor Pair Query

AtCoder Beginner Contest 308 G Minimum Xor Pair Query

时间:2023-07-03 09:01:36浏览次数:42  
标签:308 AtCoder typedef ch Xor sz int long oplus

洛谷传送门

AtCoder 传送门

考虑没有删除操作怎么做。可以动态维护 \(ans\),新加进来一个 \(x\),我们计算 \(\min\limits_{y \in S} x \oplus y\)。对 \(S\) 建 01Trie,然后从高位往低位按位贪心,在 01Trie 上优先往与 \(x\) 这一位相同的方向走,但是前提是它的子树内有数,对于 01Trie 上的每个点维护一个 \(sz_u\) 表示以 \(u\) 为根的子树内数的个数即可判断。

加上删除操作,容易线段树分治。对所有 \(3\) 操作建线段树,把一个数有效的范围对应到线段树上 \(\log\) 个区间,然后最后 dfs 一遍即可知道每个 \(3\) 操作时哪些数有效。退出线段树当前结点时的撤销,就维护之前的答案,对于这个数对应的叶子到根的路径的所有点 \(u\),将 \(sz_u\) 减去 \(1\) 即可。

时间复杂度 \(O(q \log q \log V)\)。

code
// Problem: G - Minimum Xor Pair Query
// Contest: AtCoder - AtCoder Beginner Contest 308
// URL: https://atcoder.jp/contests/abc308/tasks/abc308_g
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 300100;

int q, ch[maxn * 33][2], sz[maxn * 33], ntot, ans[maxn], res = (1 << 30);
vector<int> tree[maxn << 2];

struct node {
	int l, r, x;
	node(int a = 0, int b = 0, int c = 0) : l(a), r(b), x(c) {}
};

inline void insert(int x) {
	int p = 0;
	for (int i = 29; ~i; --i) {
		int t = ((x >> i) & 1);
		if (!ch[p][t]) {
			ch[p][t] = ++ntot;
		}
		p = ch[p][t];
		++sz[p];
	}
}

inline void erase(int x) {
	int p = 0;
	for (int i = 29; ~i; --i) {
		int t = ((x >> i) & 1);
		p = ch[p][t];
		--sz[p];
	}
}

void update(int rt, int l, int r, int ql, int qr, int x) {
	if (ql <= l && r <= qr) {
		tree[rt].pb(x);
		return;
	}
	int mid = (l + r) >> 1;
	if (ql <= mid) {
		update(rt << 1, l, mid, ql, qr, x);
	}
	if (qr > mid) {
		update(rt << 1 | 1, mid + 1, r, ql, qr, x);
	}
}

void dfs(int rt, int l, int r) {
	int lst = res;
	for (int x : tree[rt]) {
		int p = 0, s = 0;
		for (int i = 29; ~i; --i) {
			int t = ((x >> i) & 1);
			if (sz[ch[p][t]]) {
				p = ch[p][t];
			} else {
				s |= (1 << i);
				p = ch[p][t ^ 1];
			}
		}
		res = min(res, s);
		insert(x);
	}
	if (l == r) {
		ans[l] = res;
	} else {
		int mid = (l + r) >> 1;
		dfs(rt << 1, l, mid);
		dfs(rt << 1 | 1, mid + 1, r);
	}
	res = lst;
	for (int x : tree[rt]) {
		erase(x);
	}
}

void solve() {
	scanf("%d", &q);
	map< int, vector<int> > mp;
	int m = 0;
	vector<node> vc;
	for (int i = 1, op, x; i <= q; ++i) {
		scanf("%d", &op);
		if (op == 1) {
			scanf("%d", &x);
			mp[x].pb(m + 1);
		} else if (op == 2) {
			scanf("%d", &x);
			int l = mp[x].back(), r = m;
			mp[x].pop_back();
			if (l <= r) {
				vc.pb(l, r, x);
			}
		} else {
			++m;
		}
	}
	if (!m) {
		return;
	}
	for (node u : vc) {
		update(1, 1, m, u.l, u.r, u.x);
	}
	for (auto p : mp) {
		int x = p.fst;
		for (int k : p.scd) {
			if (k <= m) {
				update(1, 1, m, k, m, x);
			}
		}
	}
	dfs(1, 1, m);
	for (int i = 1; i <= m; ++i) {
		printf("%d\n", ans[i]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}


官方题解的做法挺强的。注意到对于 \(x < y < z\),\(\min(x \oplus y, y \oplus z) < x \oplus z\),于是我们只用维护值域相邻的数的 \(\oplus\) 最小值即可。

标签:308,AtCoder,typedef,ch,Xor,sz,int,long,oplus
From: https://www.cnblogs.com/zltzlt-blog/p/17521854.html

相关文章

  • AtCoder ABC307D 题解
    AtCoderABC307DMismatchedParentheses题解思路分析First——配对括号序列首先,每个右括号肯定是要与其左边最近的左括号配对。因此,我们便可以使用一个栈来进行存放左括号的下标。当有右括号时,便可以弹出栈顶元素,但是栈为空时,便无法配对。拿样例1举个例子:8a(b(d))c......
  • AtCoder Beginner Contest 308 A~F
    AtCoderBeginnerContest308手速有点慢A-NewScheme判断给定数字是否满足条件voidsolve(){ boolok=true; inta[10]; for(inti=1;i<=8;i++) cin>>a[i]; for(inti=1;i<=8;i++) { if(i>=2&&a[i]<a[i-1]) ok=......
  • AtCoder Beginner Contest 308
    A:1#include<cstdio>2#include<cstring>3#include<algorithm>4#include<iostream>5#include<string>6#include<vector>7#include<stack>8#include<bitset>9#include<cstdlib>10#include......
  • abc308
    E考虑分开处理,我们枚举中间的E,然后再枚举前面的M和后面的X分别是什么。这样的话,我们会发现,对于相同的\((A_i,A_j,A_k)\),其贡献是相同的。我们可以记录前缀和后缀中,\(A_i\)为某个值的M和X数量,然后计算个数,单独处理MEX即可。lln,pre[200005][3],suf[200005][3],a[2......
  • 【atcoder beginner 308E - MEX】
    前缀和二分查找打表枚举代码如下importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.StreamTokenizer;importjava.util.ArrayList;importjava.util.List;publicclassMain{publicstaticIntege......
  • AtCoder Grand Contest 021 E Ball Eat Chameleons
    洛谷传送门AtCoder传送门容易发现一个变色龙是红色当且仅当,设\(R\)为红球数量,\(B\)为蓝球数量,那么\(R\geB\)或\(R=B\)且最后一个球是蓝球。考虑如何判定一个颜色序列是否可行。考虑贪心。若\(R<B\)显然不行。若\(R\geB+n\),每个变色龙都可以分到比蓝球......
  • AtCoder Beginner Contest 307(E,F,G)
    AtCoderBeginnerContest307(E,F,G)E(dp)E这个题大意就是我们需要组成一个长度为\(n\)的数组,满足两个相邻的数字不可以相等,其中,\(a_1\)和\(a_n\)也是相邻的,我们可以选择的数字为\(0\)到\(m-1\),问最后有多少种不同的组成方式满足以上条件。题目大意很简单,就是有点难想,如果\(a......
  • Atcoder Beginner Contest 251-260 EFG
    #251E-TakahashiandAnimals*1261,*环形dpACLink考虑环形dp,对于使用或者不使用\(1\)号饲料分别dp,然后取最小值即可。......
  • AtCoder Beginner Contest(abc) 297
    B-chess960题目大意给定一串字符串,里面一定包含2个'B',2个'R',1个'K',问该字符串是否满足以下两个条件,一是两个'B'所在位置奇偶性不同;二是'K'的位置在两个'R'之间解题思路签到题不多嗦了;神秘代码#include<bits/stdc++.h>#defineintlonglongusi......
  • AtCoder Beginner Contest 296 Ex Unite
    洛谷传送门AtCoder传送门不错的dp。考虑按行从上往下dp,并且把列的连通状态塞进dp状态里面。实际上就是塞一个并查集。判状态合法性就是当一个竖的全黑长条结束后,有没有跟别的列连起来。code//Problem:Ex-Unite//Contest:AtCoder-AtCoderBeginnerContest29......