其他分享
首页 > 其他分享> > 冲刺国赛5月31日第十八场

冲刺国赛5月31日第十八场

作者:互联网

20220531

亿个社区(community)

题意

给你一个长度为 \(N\) 的序列 \(t\),你需要把序列分成 \(K\) 个连续子段,设第 \(i\) 个子段左端为 \(l_i\),右端为 \(r_i\),则代价为 \(\sum_{i = 1} ^ k (t_{l_i}-t_{r_i}) ^ 2\)。求最小的代价。

题解

首先有个很 naive 的 dp 就是,\(f[i][j]\) 表示 \(1\sim j\) 的序列划分为 \(j\) 段的最小代价。有一个平凡的转移是

\[f[i][j] = \min_{p = 1}^ j( f[i - 1][p - 1] + (t_p - t_j) ^ 2) \]

这个 \(dp\) 是 \(O(N ^ 2 K)\) 的。考虑如何优化,首先带上平方就很像斜率优化之类。转化为斜率优化形式,令 \(g = f[i],g'= f[i + 1]\),那么应该是

\[2 \times t_p \times t_j + g'[j] - t _j ^ 2 = g[p - 1] + t_p ^ 2 \]

那么决策点的坐标就是 \((2\times t_p,g[p - 1] + t_p ^ 2)\),我们的决策点肯定只能在下凸壳上。于是相当于是之前决策点的凸壳上找一个斜率 \(> t_j\) 的第一个点是我的决策点。

但是发现,要求的点的横坐标不递增,然后加入的决策点的横坐标也是不递增的。那么就是说,我们似乎可以维护一个凸包来找到答案。那么 \(\text{splay}\) 是个很正确的选择,但是我不会(

于是可以考虑 \(cdq\) 分治,每次左边的点按照决策点横坐标排序,右边点按照他的斜率排序。然后就可以正常计算贡献了。

要注意,斜率优化的时候最好把分母乘过去,要不然被卡哭了。

// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
	mt19937 eng;
	void init(int Seed) {return eng.seed(Seed);}
	int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
	x = 0;
	bool f = 0;
	char ch = gc();
	while (!isdigit(ch)) f = ch == '-', ch = gc();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
	if (f) x = -x;
}
inline void reads(char *s) {
	char ch = gc();
	while (isspace(ch)) ch = gc();
	while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
	*s = 0;
	return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
	read(x);
	read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
const int MAXN = 1e4 + 10, MOD = 998244353, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
	if (y < 0) {
		y %= MOD - 1;
		y += MOD - 1;
	}
	int ret = 1;
	for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
	return ret;
};
auto Mod = [] (int x) -> int {
	if (x >= MOD) return x - MOD;
	else if (x < 0) return x + MOD;
	else return x;
};
template<const int N_num, const int M_num>
struct Graph {
	int H[N_num];
	struct Edge {int to, lac;} e[M_num];
	inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
	inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
const int MAXK = 1e2 + 10;
int N, K, t[MAXN], pid[MAXN], cid[MAXN], o, hd, tl, q[MAXN];
double X[MAXN], Y[MAXN];
ll f[MAXK][MAXN];
inline ll sq(ll x) {return x * x;}
inline double slope(int x, int y) {return (Y[x] - Y[y]) / (X[x] - X[y]);}
inline bool cmp(int x, int y, int z) {
	// y -> x 的斜率大于等于 z 到 y 的
	if (X[x] == X[y]) return Y[x] < Y[y];
	else return (Y[x] - Y[y]) * (X[y] - X[z]) <= (Y[y] - Y[z]) * (X[x] - X[y]);
}
void push(int x) {
	for (; hd < tl && cmp(x, q[tl], q[tl - 1]); --tl);
	q[++tl] = x;
}
void gao(int x) {
	for (; hd < tl && (Y[q[hd]] - Y[q[hd + 1]]) >= t[x] * (X[q[hd]] - X[q[hd + 1]]); ++hd);
	chkmin(f[o][x], f[o - 1][q[hd] - 1] + sq(t[x] - t[q[hd]]));
}
int tmp[MAXN];
void cdq(int l, int r) {
	if (l == r) {
		chkmin(f[o][l], f[o - 1][l - 1]);
		X[l] = 2 * t[l];
		Y[l] = f[o - 1][l - 1] + sq(t[l]);
		return;
	}
	int mid = (l + r) / 2;
	*tmp = 0;
	for (int i = l; i <= r; ++i) if (cid[i] <= mid) tmp[++*tmp] = cid[i];
	for (int i = l; i <= r; ++i) if (cid[i] > mid) tmp[++*tmp] = cid[i];
	for (int i = 1; i <= *tmp; ++i) cid[i + l - 1] = tmp[i];
	cdq(l, mid);
	hd = 1, tl = 0;
	for (int i = l; i <= mid; ++i) push(pid[i]);
	for (int i = mid + 1; i <= r; ++i) gao(cid[i]);
	cdq(mid + 1, r);
	*tmp = 0;
	for (int i = l, j = mid + 1; i <= mid || j <= r; ) {
		if (j > r || (i <= mid && X[pid[i]] <= X[pid[j]])) tmp[++*tmp] = pid[i++];
		else tmp[++*tmp] = pid[j++];
	}
	for (int i = 1; i <= *tmp; ++i) pid[l + i - 1] = tmp[i];
}
int main() {
	freopen("community.in", "r", stdin);
	freopen("community.out", "w", stdout);
	// std::ios::sync_with_stdio(0);
	// cout << std::fixed << std::setprecision(8);
	// cin.tie(0);
	// cout.tie(0);
	qwq::init(20050112);
	memset(f, 63, sizeof f);
	read(N, K);
	if (K >= N) {
		puts("0");
		return 0;
	}
	for (int i = 1; i <= N; ++i) read(t[i]);
	for (int i = 1; i <= N; ++i) f[1][i] = sq(t[i] - t[1]);
	for (o = 2; o <= K; ++o) {
		for (int j = 1; j <= N; ++j) pid[j] = cid[j] = j;
		sort(cid + 1, cid + 1 + N, [&] (const int &x, const int &y) {return t[x] < t[y];});
		cdq(1, N);
		// for (int i = 1; i <= N; ++i)
	}
	printf("%lld\n", f[K][N]);
	// cout << (-3 / 2);
	cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
	return (0-0);
}

亿点整理(sort)

题意

给你一个一共有 \(2N\) 个点的二分图,两点之间有边或者没有边(没有边则输入 \(-1\)),问你他是否存在一个权重为 \(K\) 的倍数的完美匹配。

\(1\le N,K\le 100\)。

题解

有一个检查二分图是否存在完美匹配的方法是,随机一个 $(\mathbb{N}_+) ^ {n\times n} $,比如叫做 \(X\),然后令

\[M_{i,j} = \begin{cases} 0& f_{i, j} = -1\\ X_{i, j} & f_{i,j} \not = -1 \end{cases} \]

然后如果 \(\det (M) \not = 0\) 的话,就有一个合法的完美匹配。

可以多次随机。

说明的话,可以考虑行列式的定义即可。

考虑这道题怎么运用这个做法,我们要求比如满足完美匹配 \(S\bmod K = 0\),那么我们求 \(\det (M)\cdot [K|S]\) 即可。

我们考虑用单位根代替后面的东西。

今天才知道的欧拉公式 \(e ^ {ix} = \cos x + i \sin x\)

\[\sum_{j = 0} ^ {K- 1} (e^{\frac{i2\pi S}{K}}) ^ j = K[K|S] \]

其实这个 \(K\) 可以不考虑,反正我们只要求他是不是 \(0\),记 \(e^{\frac{i2\pi }{K}} = \omega_k\),代入有:

\[\begin{aligned} \det(M) [K|S]&= \left(\sum_{p}\left(-1\right) ^ {\sigma (p)}\prod _{k = 1} ^ {n} M_{k,p(k)}\right)\left( \sum_{i = 0} ^ {K - 1} \omega_{K}^{Si} \right) \\ &=\sum_{p}\left(-1\right) ^ {\sigma (p)}\left( \sum_{i = 0} ^ {K - 1} \omega_{K}^{Si} \right)\prod _{k = 1} ^ {n} M_{k,p(k)} \\ &= \sum_{p}\left(-1\right) ^ {\sigma (p)}\sum_{i = 0} ^ {K - 1}\left(\prod_{k = 1} ^ n \omega_{K} ^ {i\cdot f_{k, p(k)}}\right)\left(\prod _{k = 1} ^ n M_{k, p(k)}\right)\\ &= \sum_{i = 0} ^ {K - 1}\sum_{p} (-1)^ {\sigma(p)} \prod_{k = 1} ^ nM_{k, p(k)}\cdot \omega_{K}^{i \cdot f_{k, p(k)}} \end{aligned} \]

然后就可以转化为 \(\sum_{i = 0}^ {K - 1} \det(M_i)\) 的形式去做了。

用复数很麻烦,怎么办?

我们考虑可以转化为原根类似物,你找到一个 \(P\) 满足 \(K|\varphi (P)\) ,再找一个阶为 \(K\) 的数字,比如 \(\omega = g ^ {\frac{\varphi(p)}{K}}\)。

// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
	mt19937 eng;
	void init(int Seed) {return eng.seed(Seed);}
	int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
	x = 0;
	bool f = 0;
	char ch = gc();
	while (!isdigit(ch)) f = ch == '-', ch = gc();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
	if (f) x = -x;
}
inline void reads(char *s) {
	char ch = gc();
	while (isspace(ch)) ch = gc();
	while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
	*s = 0;
	return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
	read(x);
	read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
int MOD = 998244353;
const int MAXN = 105, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
	if (y < 0) {
		y %= MOD - 1;
		y += MOD - 1;
	}
	int ret = 1;
	for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
	return ret;
};
auto Mod = [] (int x) -> int {
	if (x >= MOD) return x - MOD;
	else if (x < 0) return x + MOD;
	else return x;
};
template<const int N_num, const int M_num>
struct Graph {
	int H[N_num];
	struct Edge {int to, lac;} e[M_num];
	inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
	inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
int a[MAXN][MAXN], p[MAXN][MAXN], t[MAXN][MAXN];
const int M[] = { 0,          0,          1073741827, 1073741827, 1073741833, 1073741831, 1073741827,
                  1073741831, 1073741833, 1073741833, 1073741831, 1073741857, 1073741833, 1073741839,
                  1073741831, 1073741971, 1073741857, 1073742169, 1073741833, 1073741833, 1073742361,
                  1073741971, 1073741857, 1073741891, 1073741833, 1073742851, 1073741839, 1073741833,
                  1073742209, 1073742053, 1073741971, 1073742289, 1073741857, 1073741857, 1073742169,
                  1073741831, 1073741833, 1073742073, 1073741833, 1073741839, 1073742361, 1073742113,
                  1073741971, 1073741993, 1073741857, 1073742391, 1073741891, 1073742073, 1073741857,
                  1073742391, 1073742851, 1073742169, 1073741969, 1073742053, 1073741833, 1073742671,
                  1073742209, 1073741833, 1073742053, 1073741827, 1073742361, 1073747621, 1073742289,
                  1073742391, 1073741953, 1073741891, 1073741857, 1073742403, 1073742169, 1073742259,
                  1073741831, 1073745781, 1073741833, 1073743861, 1073742073, 1073743051, 1073741833,
                  1073742209, 1073741839, 1073742721, 1073742721, 1073741833, 1073742113, 1073745769,
                  1073742517, 1073743291, 1073741993, 1073742169, 1073741857, 1073743883, 1073742391,
                  1073742671, 1073742673, 1073742289, 1073742073, 1073744911, 1073741857, 1073742277,
                  1073742391, 1073742517, 1073743501 };
const int G[] = { 0, 0,  2,  2, 5, 13, 2, 13, 5, 5,  13, 5, 5,  3, 13, 2,  5, 7, 5,  5, 7, 2, 5, 6, 5, 2,
                  3, 5,  3,  2, 2, 37, 5, 5,  7, 13, 5,  5, 5,  3, 7,  5,  2, 3, 5,  6, 6, 5, 5, 6, 2, 7,
                  3, 2,  5,  7, 3, 5,  2, 2,  7, 2,  37, 6, 10, 6, 5,  2,  7, 2, 13, 2, 5, 6, 5, 2, 5, 3,
                  3, 11, 11, 5, 5, 7,  6, 2,  3, 7,  5,  2, 6,  7, 5,  37, 5, 6, 5,  5, 6, 6, 2 };
int Det(int a[MAXN][MAXN], int n) {
	int ans = 1, flag = 0;
	for (int i = 1; i <= n; ++i) {
		int pos = 0;
		for (int j = i; j <= n; ++j) if (a[j][i]) {
			pos = j;
			break;
		}
		if (!pos) return 0;
		if (i != pos) swap(a[i], a[pos]), flag ^= 1;
		ans = (ll) ans * a[i][i] % MOD;
		int inv = Ksm(a[i][i], -1);
		for (int j = i + 1; j <= n; ++j) {
			int d = (ll) inv * a[j][i] % MOD;
			for (int k = i; k <= n; ++k) a[j][k] = Mod(a[j][k] - (ll) d * a[i][k] % MOD);
		}
	}
	return flag ? MOD - ans : ans;
}
int N, K, g, pw[MAXN];
int main() {
	freopen("sort.in", "r", stdin);
	freopen("sort.out", "w", stdout);
	// std::ios::sync_with_stdio(0);
	// cout << std::fixed << std::setprecision(8);
	// cin.tie(0);
	// cout.tie(0);
	qwq::init(20050112);
	read(N, K);
	if (K == 1) K = 2;
	for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j) read(a[i][j]);
	MOD = M[K];
	g = G[K];
	for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j) p[i][j] = qwq::rnd(1, MOD - 1);
	int ans = 0;
	for (int C = 0; C < K; ++C) {
		pw[0] = 1;
		pw[1] = Ksm(g, (MOD - 1) / K * C);
		for (int i = 2; i < K; ++i) pw[i] = (ll) pw[i - 1] * pw[1] % MOD;
		for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j) t[i][j] = (~a[i][j]) ? (ll) p[i][j] * pw[a[i][j]] % MOD : 0;
		int x = Det(t, N);
		ans = Mod(ans + x);
	}
	puts(ans ? "Yes" : "No");
	// cout << (-3 / 2);
	cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
	return (0-0);
}

亿块田(farm)

题意

维护一个长度为 \(N\) 的序列 \(a\),有三种操作

\(N\le 2\times 10^ 5,0\le x \le 2^{20}\)

题解

令 \(k = \log V\),我们考虑维护一些等价类之类的东西,就是说,全部与或者或数字之后相对大小关系不变。

什么时候这样子?比如你维护所有数字与的答案(\(\text{and}\)),或(\(\text{or}\))的答案。如果与上一个 \(qx\),然后如果 \(qx\) 里是 \(0\) 的位,如果所有数字里都这个位都是 \(0\)(或者都是 \(1\))就是一个等价类。

对于或也同样考虑,对于 \(qx\) 里面每个是 \(1\) 的为,如果如果所有数字里都这个位都是 \(0\)(或者都是 \(1\))就是一个等价类。

然后每次可以对同一个等价类的节点直接给标记。

怎么分析时间复杂度?

定义 \(\phi(x) = \phi(L) + \phi(R) + f(x)\),然后 \(\phi(root)\) 是全局势能。

定义对于节点 \(f(x) = \sum_{k} g(x, k)\) 表示区间内的数字在第 \(k\) 位上是不是一模一样。初始的时候 \(\Phi = \phi(root) = nk\log n\)。

最后 \(\Phi \le (n + q)k\log n\),所以复杂度为 \(O((n + q)k\log n)\)。

// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
	mt19937 eng;
	void init(int Seed) {return eng.seed(Seed);}
	int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
	x = 0;
	bool f = 0;
	char ch = gc();
	while (!isdigit(ch)) f = ch == '-', ch = gc();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
	if (f) x = -x;
}
inline void reads(char *s) {
	char ch = gc();
	while (isspace(ch)) ch = gc();
	while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
	*s = 0;
	return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
	read(x);
	read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
const int MAXN = 262144, MOD = 998244353, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
	if (y < 0) {
		y %= MOD - 1;
		y += MOD - 1;
	}
	int ret = 1;
	for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
	return ret;
};
auto Mod = [] (int x) -> int {
	if (x >= MOD) return x - MOD;
	else if (x < 0) return x + MOD;
	else return x;
};
template<const int N_num, const int M_num>
struct Graph {
	int H[N_num];
	struct Edge {int to, lac;} e[M_num];
	inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
	inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
using ui = unsigned int;
int N;
struct Node {
	ui or_val, and_val, or_tag, and_tag, mx;
	void clear() {or_tag = 0; and_tag = -1;}
	void operator |= (ui v) {and_val |= v, or_val |= v, and_tag |= v, or_tag |= v, mx |= v;}
	void operator &= (ui v) {and_val &= v, or_val &= v, and_tag &= v, or_tag &= v, mx &= v;}
	ui good() {return ~(and_val ^ or_val);}
} nd[MAXN * 4];
#define or_val(i) nd[i].or_val
#define and_val(i) nd[i].and_val
#define or_tag(i) nd[i].or_tag
#define and_tag(i) nd[i].and_tag
#define mx(i) nd[i].mx
inline void up(int k) {
	mx(k) = max(mx(ls(k)), mx(rs(k)));
	and_val(k) = and_val(ls(k)) & and_val(rs(k));
	or_val(k) = or_val(ls(k)) | or_val(rs(k));
}
void down(int k) {
	nd[ls(k)] &= and_tag(k);
	nd[ls(k)] |= or_tag(k);
	nd[rs(k)] &= and_tag(k);
	nd[rs(k)] |= or_tag(k);
	nd[k].clear();
}
ui A[MAXN];
void build() {
	function<void(int, int, int)> dfs = [&] (int k, int l, int r) {
		nd[k].clear();
		if (l == r) {
			and_val(k) = or_val(k) = mx(k) = A[l];
			return;
		}
		int mid = (l + r) / 2;
		dfs(ls(k), l, mid);
		dfs(rs(k), mid + 1, r);
		up(k);
	};
	dfs(1, 1, N);
}
void mfy_and(int ql, int qr, ui qx) {
	function<void(int, int, int)> dfs = [&] (int k, int l, int r) {
		if (l == r || (ql <= l && r <= qr && (nd[k].good() & (~qx)) == (~qx))) {
			nd[k] &= qx;
			return;
		}
		int mid = (l + r) / 2;
		down(k);
		if (ql <= mid) dfs(ls(k), l, mid);
		if (mid < qr) dfs(rs(k), mid + 1, r);
		up(k);
	};
	dfs(1, 1, N);
}
void mfy_or(int ql, int qr, ui qx) {
	function<void(int, int, int)> dfs = [&] (int k, int l, int r) {
		if (l == r || (ql <= l && r <= qr && (nd[k].good() & qx) == qx)) {
			nd[k] |= qx;
			return;
		}
		down(k);
		int mid = (l + r) / 2;
		if (ql <= mid) dfs(ls(k), l, mid);
		if (mid < qr) dfs(rs(k), mid + 1, r);
		up(k);
	};
	dfs(1, 1, N);
}
ui qry(int ql, int qr) {
	function<ui(int, int, int)> dfs = [&] (int k, int l, int r) -> ui {
		if (ql <= l && r <= qr) return mx(k);
		int mid = (l + r) / 2;
		ui ret = 0;
		down(k);
		if (ql <= mid) chkmax(ret, dfs(ls(k), l, mid));
		if (mid < qr) chkmax(ret, dfs(rs(k), mid + 1, r));
		return ret;
	};
	return dfs(1, 1, N);
}
int Q;
int main() {
	freopen("farm.in", "r", stdin);
	freopen("farm.out", "w", stdout);
	// std::ios::sync_with_stdio(0);
	// cout << std::fixed << std::setprecision(8);
	// cin.tie(0);
	// cout.tie(0);
	qwq::init(20050112);
	read(N, Q);
	for (int i = 1; i <= N; ++i) read(A[i]);
	build();
	ui x;
	for (int opt, l, r; Q--; ) {
		read(opt, l, r);
		if (opt == 1) read(x), mfy_and(l, r, x);
		else if (opt == 2) read(x), mfy_or(l, r, x);
		else printf("%u\n", qry(l, r));
	}
	// cout << (-3 / 2);
	cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
	return (0-0);
}

标签:std,ch,return,第十八,int,31,国赛,inline,using
来源: https://www.cnblogs.com/siriehn-nx/p/16332007.html