洛谷 P8955 「VUSC」Card Tricks

发布时间 2023-11-23 18:34:01作者: zltzlt

洛谷传送门

很显然每个数的每一位最多只会修改一遍。于是拆位,每一位开个并查集,存下一个不拥有这一位的数,就可以暴力修改了。

但是空间是 \(O(n \log V)\) 的,炸了。于是可以考虑手写 i24 类,同时并查集寻找祖先不要用递归版的路径压缩,然后就过了。

code
// Problem: P8955 「VUSC」Card Tricks
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P8955
// Memory Limit: 100 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 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;

bool Mst;

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 20], *p1 = buf, *p2 = buf;
inline int read() {
    char c = getchar();
    int x = 0;
    for (; !isdigit(c); c = getchar()) ;
    for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x;
}

const int maxn = 1000100;

int n, m, K, a[maxn], ans[maxn];

struct i24 {
	unsigned char a, b, c;
	
	inline void set(int x) {
		a = x & 255;
		b = (x >> 8) & 255;
		c = (x >> 16) & 255;
	}
	
	inline int val() {
		return a + ((int)b << 8) + ((int)c << 16);
	}
} fa[30][maxn];

inline int find(int k, int x) {
	while (fa[k][x].val() != x) {
		int t = fa[k][fa[k][x].val()].val();
		fa[k][x].set(t);
		x = t;
	}
	return x;
}

void solve() {
	n = read();
	m = read();
	K = read();
	for (int i = 1; i <= n; ++i) {
		a[i] = read();
		ans[i] = -1;
	}
	for (int j = 0; j < 30; ++j) {
		for (int i = 1; i <= n + 1; ++i) {
			fa[j][i].set((a[i] & (1 << j)) ? i + 1 : i);
		}
	}
	for (int t = 1, l, r, x; t <= m; ++t) {
		l = read();
		r = read();
		x = read();
		for (int j = 0; j < 30; ++j) {
			if ((~x) & (1 << j)) {
				continue;
			}
			for (int i = find(j, l); i <= r; i = find(j, i)) {
				a[i] |= (1 << j);
				if (a[i] > K && ans[i] == -1) {
					ans[i] = t;
				}
				fa[j][i].set(i + 1);
			}
		}
	}
	for (int i = 1; i <= n; ++i) {
		printf("%d ", ans[i]);
	}
}

bool Med;

int main() {
	fprintf(stderr, "%.2lf MB\n", (&Mst - &Med) / 1048576.);
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}