ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-05-31 20:04:55  阅读:117  来源: 互联网

标签:std ch return 第十八 int 31 国赛 inline using


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\),有三种操作

  • 1 l r x 将 \([l,r]\) 之间的数字按位与 \(x\)。
  • 2 l r x 将 \([l,r]\) 之间的数字按位或 \(x\)。
  • 3 l r 求 \([l,r]\) 之间的数字最大值。

\(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\)。

  • 每次修改的增加势能 \(\Delta_{\Phi} = k\log N\)
  • 每次下放标记时候增加势能 \(\Delta _{\Phi} = k\)
  • 每次访问一个线段树节点会减少 \(1\) 的势能。

最后 \(\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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有