首页 > 其他分享 >CodeForces 1936D Bitwise Paradox

CodeForces 1936D Bitwise Paradox

时间:2024-03-01 20:11:59浏览次数:25  
标签:pre suf Paradox int scd CodeForces back 1936D res

洛谷传送门

CF 传送门

CF1004F Sonya and Bitwise OR 很像。

考虑一次询问怎么做。考虑分治,每次只计算左端点在 \([l, mid]\),右端点在 \([mid + 1, r]\) 的区间的贡献。对于每个 \(i \in [l, mid]\),维护最小的 \(j \in [mid + 1, r]\) 使得 \([i, j]\) 的或 \(\ge v\),那么 \(\max\limits_{k = i}^j a_k\) 对答案有贡献。

考虑带修怎么做。考虑套上线段树,利用线段树的分治结构,问题变成了如何合并两个区间的答案。

按位或有个很好的性质,就是前(或后)缀的或只会变化 \(O(\log V)\) 次。所以我们对于线段树上每个结点,维护前缀和后缀的或第一次变化的位置。

计算左端点在左结点,右端点在右结点的区间贡献,就枚举左结点所有后缀或第一次变化的位置作为左端点,双指针维护使得区间或 \(\ge v\) 的最靠左的右端点即可。

注意到 \(a\) 不变,可以使用 ST 表单次 \(O(1)\) 计算 \(a\) 的区间最大值。合并两个区间的复杂度为 \(O(\log V)\)。所以总时间复杂度为 \(O((n + q) \log n \log V)\)。

code
// Problem: D. Bitwise Paradox
// Contest: Codeforces - Codeforces Round 930 (Div. 1)
// URL: https://codeforces.com/problemset/problem/1936/D
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#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 = 200100;
const int logn = 20;

ll n, m, q, a[maxn], b[maxn], f[logn][maxn];

inline ll qmax(int l, int r) {
	int k = __lg(r - l + 1);
	return max(f[k][l], f[k][r - (1 << k) + 1]);
}

struct node {
	ll ans;
	vector<pii> pre, suf;
	node() {
		ans = 0;
		vector<pii>().swap(pre);
		vector<pii>().swap(suf);
	}
};

inline node operator + (const node &a, const node &b) {
	node res;
	res.ans = min(a.ans, b.ans);
	res.pre = a.pre;
	for (pii p : b.pre) {
		if ((res.pre.back().scd | p.scd) != res.pre.back().scd) {
			res.pre.pb(p.fst, res.pre.back().scd | p.scd);
		}
	}
	res.suf = b.suf;
	for (pii p : a.suf) {
		if ((res.suf.back().scd | p.scd) != res.suf.back().scd) {
			res.suf.pb(p.fst, res.suf.back().scd | p.scd);
		}
	}
	int j = (int)b.pre.size() - 1;
	for (pii p : a.suf) {
		while (j && (p.scd | b.pre[j - 1].scd) >= m) {
			--j;
		}
		if ((p.scd | b.pre[j].scd) >= m) {
			res.ans = min(res.ans, qmax(p.fst, b.pre[j].fst));
		}
	}
	return res;
}

namespace SGT {
	node a[maxn << 2];
	
	inline void pushup(int x) {
		a[x] = a[x << 1] + a[x << 1 | 1];
	}
	
	void build(int rt, int l, int r) {
		if (l == r) {
			a[rt].ans = (b[l] >= m ? ::a[l] : 9e18);
			a[rt].pre = a[rt].suf = vector<pii>(1, mkp(l, b[l]));
			return;
		}
		int mid = (l + r) >> 1;
		build(rt << 1, l, mid);
		build(rt << 1 | 1, mid + 1, r);
		pushup(rt);
	}
	
	void update(int rt, int l, int r, int x, ll y) {
		if (l == r) {
			a[rt].ans = (y >= m ? ::a[l] : 9e18);
			a[rt].pre = a[rt].suf = vector<pii>(1, mkp(l, y));
			return;
		}
		int mid = (l + r) >> 1;
		(x <= mid) ? update(rt << 1, l, mid, x, y) : update(rt << 1 | 1, mid + 1, r, x, y);
		pushup(rt);
	}
	
	node query(int rt, int l, int r, int ql, int qr) {
		if (ql <= l && r <= qr) {
			return a[rt];
		}
		int mid = (l + r) >> 1;
		if (qr <= mid) {
			return query(rt << 1, l, mid, ql, qr);
		} else if (ql > mid) {
			return query(rt << 1 | 1, mid + 1, r, ql, qr);
		} else {
			return query(rt << 1, l, mid, ql, qr) + query(rt << 1 | 1, mid + 1, r, ql, qr);
		}
	}
}

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		f[0][i] = a[i];
	}
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &b[i]);
	}
	for (int j = 1; (1 << j) <= n; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
			f[j][i] = max(f[j - 1][i], f[j - 1][i + (1 << (j - 1))]);
		}
	}
	SGT::build(1, 1, n);
	scanf("%lld", &q);
	while (q--) {
		ll op, x, y;
		scanf("%lld%lld%lld", &op, &x, &y);
		if (op == 1) {
			SGT::update(1, 1, n, x, y);
		} else {
			ll ans = SGT::query(1, 1, n, x, y).ans;
			printf("%lld ", ans > 1e18 ? -1LL : ans);
		}
	}
	putchar('\n');
}

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

标签:pre,suf,Paradox,int,scd,CodeForces,back,1936D,res
From: https://www.cnblogs.com/zltzlt-blog/p/18047851

相关文章

  • Codeforces 839E Mother of Dragons
    令\(s_u\)为点\(u\)分配到的权值。结论:最后选出来有权值的肯定是一个最大团。考虑反证,如果\(x,y\)间没有连边,则\(x,y\)的贡献是独立的,若\(\sum\limits_{(u,x)\inE}s_u\ge\sum\limits_{(v,y)\inE}s_v\),那么就可以把\(s_y\)给\(s_x\),否则把\(s_x\)给\(s_......
  • Codeforces 1406E Deleting Numbers
    考虑询问每个质因子及其次数最后组合得到\(n\)。注意到\(n\)最多只会有\(1\)个\(>\sqrt{n}\)的质因子。于是考虑分成\(\le\sqrt{n}\)和\(>\sqrt{n}\)来考虑。对于\(\le\sqrt{n}\)的\(p\)。考虑先\(\texttt{B}\p\),那么还剩下的\(p\)的倍数就只有\(x\)......
  • Codeforces Round 930 (Div. 2) - sol
    20240301由于笔者实力较弱,所以这只是Div2的题解。四年一次的比赛啊,还是要打。Dashboard-CodeforcesRound930(Div.2)-CodeforcesA.ShufflePartyYouaregivenanarray\(a_1,a_2,\ldots,a_n\).Initially,\(a_i=i\)foreach\(1\lei\len\).Theopera......
  • Codeforces 1446D1 Frequency Problem (Easy Version)
    考虑求出全局的众数\(A\)。那么有一个结论,就是答案区间的众数中绝对有\(A\)。考虑反证法,如果没有\(A\),\(A\)在序列中出现的个数一定\(\ge\)区间内众数的出现个数,所以可以一直往外扩展直到\(A\)出现的个数与区间内非\(A\)众数的个数持平,这样肯定更优。于是可以考虑钦......
  • Codeforces 1446D2 Frequency Problem (Hard Version)
    考虑求出全局的众数\(A\)。那么有一个结论,就是答案区间的众数中绝对有\(A\)。考虑反证法,如果没有\(A\),\(A\)在序列中出现的个数一定\(\ge\)区间内众数的出现个数,所以可以一直往外扩展直到\(A\)出现的个数与区间内非\(A\)众数的个数持平,这样肯定更优。于是可以考虑钦......
  • Codeforces 932D Tree
    首先有个动态加叶子的操作,考虑到树剖需要离线下来预处理,便考虑用倍增来维护。首先要找到\(\gea_u\)的最深的父亲\(v\),便可以先用倍增处理好长度为\(2^i\)的链上的\(\max\)。如果\(\max<a_u\),就往上跳,跳不了就是到点\(v\)了。考虑连边\(v\tou\),这仍然会是一棵树(建......
  • Codeforces 1455E Four Points
    首先确定每个点最后走到的是哪一个点。这部分可以枚举全排列。假设左上角的点为\((x_0,y_0)\),右上角的点为\((x_1,y_1)\),左下角的点为\((x_2,y_2)\),右下角的点为\((x_3,y_3)\)。令最终的点为\((x'_0,y'_0)\),以此类推。那么最终的答案就是\(\sum\limits_{i=0}^3|......
  • Codeforces 451E Devu and Flowers
    首先考虑没有\(f_i\)的限制的时候,此时可以用插板法得到方案数为\(\binom{s+n-1}{n-1}\)。考虑钦定\(f_i\)不合法,那么就相当于先在\(i\)这里选\(f_i+1\),剩下的随意分配,方案数就为\(\binom{s-(f_i+1)+n-1}{n-1}\)。算完过后能发现会算重存在\(>1\)......
  • Codeforces 1830C Hyperregular Bracket Strings
    考虑到区间的限制\([l,r]\)就是要求\([l,r]\)里的字符会在\([l,r]\)里找到匹配。假设还有个区间\([l',r']\)满足\(l\lel'\ler\ler'\),能够发现限制变成了\([l,l'),[l',r],(r,r']\)这\(3\)个区间内的字符能在对应区间内找到匹配。继续,假设\(l\lel'\le......
  • Codeforces 863E Turn Off The TV
    能发现其实就是区间加查询区间最小值。如果最小值\(>1\)则这个区间可以删掉。考虑离散化端点,先把区间表示为\([l_i,r_i)\)的形式,方便离散化端点。这样子离散化出来的端点也是\([x,y)\)的形式。对于区间加查询区间最小值,很容易用线段树维护。时间复杂度\(O(n\logn)......