社区讨论

为何RE0分,必关n人

P4036[JSOI2008] 火星人参与者 3已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mj4c6m01
此快照首次捕获于
2025/12/13 21:33
2 个月前
此快照最后确认于
2025/12/16 14:50
2 个月前
查看原帖
范浩强Treap
CPP
#include <cstdio>
#include <random>
#include <ctime>
#include <iostream>
#include <string>
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef long double ld;
const int MAXSZ = 1 << 20;
char ch, buf[MAXSZ], *p1, *p2;
int HelloCCF;
#define ge() (p1 == p2 && (p2 = buf + fread(p1 = buf, 1, MAXSZ, stdin), p1 == p2) ? EOF : *p1++)
#define end() putchar('\n')
#define Debug() printf("I Love Furina forever! * %d\n", ++ HelloCCF);
template <typename T_T>
inline void read(T_T &x) {
	x = 0;
	
	while (ch < '0' || '9' < ch) ch = ge();
	while ('0' <= ch && ch <= '9') {
		x = x * 10 + (ch ^ 48);
		ch = ge();
	}
}
template <typename T_T>
inline void write(T_T x) {
	if (x > 9) write(x / 10);
	putchar(x % 10 | 48);
}
template <typename T_T>
inline T_T min(T_T a, T_T b) {return a < b ? a : b;}
template <typename T_T>
inline T_T max(T_T a, T_T b) {return a > b ? a : b;}
std::mt19937 mt((ull)time(0) ^ 33241);

const int N = 1e5 + 5, P = 131;

ull tag[N];
std::string CNUM;
struct FHQ {
	FHQ *son[2];
	char val;
	int sz;
	ui heap;
	ull num;
}*null, *root;
inline void push_up(FHQ *u) {
	u -> sz = u -> son[0] -> sz + u -> son[1] -> sz + 1;
	u -> num = u -> son[0] -> num * tag[u -> son[1] -> sz + 1] + (u -> val - 'a' + 1) * tag[u -> son[1] -> sz] + u -> son[1] -> num;
}
void build(FHQ *&u, int l, int r) {
	if (l > r) return ;

	int mid = (l + r) >> 1;
	u = new FHQ; *u = {{null, null}, CNUM[mid - 1], 0, mt(), 0};
	
	build(u -> son[0], l, mid - 1);
	build(u -> son[1], mid + 1, r);
	push_up(u);
}
void split(FHQ *u, int rank, FHQ *&A, FHQ *&B) {
	if (u == null) {
		A = B = null;
		return ;
	}

	if (u -> son[0] -> sz < rank) {
		A = u;
		split(u -> son[1], rank - u -> son[0] -> sz - 1, u -> son[1], B);
	}
	else {
		B = u;
		split(u -> son[0], rank, A, u -> son[0]);
	}
	push_up(u);
}
FHQ *merge(FHQ *u, FHQ *v) {
	if (u == null) return v;
	if (v == null) return u;

	if (u -> heap > v -> heap) {
		u -> son[1] = merge(u -> son[1], v);
		push_up(u);
	}
	else {
		v -> son[0] = merge(u, v -> son[0]);
		push_up(v);
	}
}
ull get_hash(int l, int r) {
	if (l > r) return 1;

	FHQ *root1 = null, *root2 = null;
	split(root, l - 1, root, root1);
	split(root1, r - l + 1, root1, root2);

	ull ans = root1 -> num;
	root = merge(merge(root, root1), root2);
	return ans;
}
void solve(int x, int y) {
	if (x > y) std::swap(x, y);

	int l = 0, r = root -> sz - y + 1, res = 0;
	while (l <= r) {
		int mid = l + r >> 1;
		ull num1 = get_hash(x, x + mid - 1), num2 = get_hash(y, y + mid - 1);

		if (num1 == num2) {
			l = mid + 1;
			res = mid;
		}
		else r = mid - 1;
	}

	std::cout << res << '\n';
}

int main() {
	// freopen("Ryan.in", "r", stdin);
	// freopen("Ryan.out", "w", stdout);
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);

	null = new FHQ; *null = {{null, null}, 'a', 0, 0, 0};
	root = null;
	tag[0] = 1;
	for (int i = 1; i <= N - 5; i++) tag[i] = tag[i - 1] * P;
	std::cin >> CNUM;
	
	build(root, 1, CNUM.size());
	int T; std::cin >> T;
	while (T --) {
		char type; std::cin >> type;

		if (type == 'Q') {
			int l, r; std::cin >> l >> r;
			solve(l, r);
		}
		if (type == 'R') {
			int l; 
			char val; std::cin >> l >> val;
			FHQ *root1 = null, *root2 = null;

			split(root, l - 1, root, root1);
			split(root1, 1, root1, root2);

			root1 -> val = val;
			root = merge(root, merge(root1, root2));
		}
		if (type == 'I') {
			int l;
			char val; std::cin >> l >> val;
			FHQ *root1 = null, *root2 = new FHQ;
			*root2 = {{null, null}, val, 1, mt(), 0};

			split(root, l, root, root1);
			root = merge(root, merge(root2, root1));
		}
	}
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...