Submission #1223481

#TimeUsernameProblemLanguageResultExecution timeMemory
1223481trideserCrossing (JOI21_crossing)C++20
100 / 100
437 ms11284 KiB
#include <bits/stdc++.h>
using namespace std;

#define mod 0x7fffffff

struct SegmentTree {
	vector<long long> hash;
	vector<char> upd;
	int size;
	int depth;
	int constant;
	vector<long long> powers;
	vector<long long> powers_prefix;
	SegmentTree(int N, vector<char> vec, int a) {
		size = 1;
		depth = 0;
		constant = a;
		while(size < N) {
			size *= 2;
			depth++;
		}
		powers = vector<long long>(N);
		powers_prefix = vector<long long>(N);
		powers[0] = 1;
		powers_prefix[0] = 1;
		for(int i = 1; i < N; i++) {
			powers[i] = (powers[i - 1] * constant) % mod;
			powers_prefix[i] = (powers_prefix[i - 1] + powers[i]) % mod;
		}

		hash = vector<long long>(2 * size);
		upd = vector<char>(2 * size, 0);
		long long curhash = 0;
		for(int i = 0; i < vec.size(); i++) {
			curhash = (powers[i] * vec[i]) % mod;
			hash[size + i] = curhash;
		}
		for(int i = depth - 1; i >= 0; i--) {
			for(int j = 0; j < (1 << i); j++) {
				int node = (1 << i) + j;
				hash[node] = (hash[2 * node] + hash[2 * node + 1]) % mod;
			}
		}
	}
	long long pref(int a, int b) {
		return ((powers_prefix[b] - (a == 0 ? 0 : powers_prefix[a - 1])) % mod + mod) % mod;
	}
	void propagate(int node, int d) {
		if(upd[node] == 0x0)
			return;
		int index = node - (1 << d);
		if(d != depth) {
			upd[2 * node] = upd[node];
			upd[2 * node + 1] = upd[node];
			//cout << "C";
		}
		hash[node] = (pref((1 << (depth - d)) * index, (1 << (depth - d)) * (index + 1) - 1) * upd[node]) % mod;
		//cout << "P: " << node << " " << d << " " << (1 << depth - d) * index << " " << (1 << (depth - d)) * (index + 1) - 1 << "\n";
		upd[node] = 0x0;
	}
	void set(int begin, int end, char ch) {
		int a = 0;
		int b = 0;
		for(int i = 0; i < depth; i++) {
			int layersize = (1 << (depth - i));
			int aindex = (1 << i) + a;
			int bindex = (1 << i) + b;
			int na, nb;
			//cout << a << " " << b << " " << a * layersize + layersize / 2 << " " << b * layersize + layersize / 2<< "\n";
			propagate(aindex, i);
			propagate(bindex, i);
			if(a * layersize + layersize / 2 <= begin) {
				//cout << "r";
				// branch right
				na = 2 * a + 1;
			}
			else {
				//cout << "l";
				// branch left
				na = 2 * a;
				if(a != b) {
					upd[aindex * 2 + 1] = ch;
				}
			}
			if(b * layersize + layersize / 2 <= end) {
				//cout << "r";
				// branch right
				nb = 2 * b + 1;
				if(a != b) {
					upd[bindex * 2] = ch;
				}
			}
			else {
				//cout << "l";
				// branch left
				nb = 2 * b;
			}
			//cout << "\n";
			a = na;
			b = nb;
		}
		int aindex = (1 << depth) + a;
		int bindex = (1 << depth) + b;
		upd[aindex] = ch;
		upd[bindex] = ch;
		propagate(aindex, depth);
		propagate(bindex, depth);
		aindex /= 2;
		bindex /= 2;
		for(int i = depth - 1; i >= 0; i--) {
			propagate(aindex, i);
			propagate(2 * aindex, i + 1);
			propagate(2 * aindex + 1, i + 1);
			hash[aindex] = (hash[2 * aindex] + hash[2 * aindex + 1]) % mod;

			propagate(bindex, i);
			propagate(2 * bindex, i + 1);
			propagate(2 * bindex + 1, i + 1);
			hash[bindex] = (hash[2 * bindex] + hash[2 * bindex + 1]) % mod;

			aindex /= 2;
			bindex /= 2;
		}
	}
	long long get(int begin, int end) {
		int a = 0;
		int b = 0;
		long long ret = 0;
		for(int i = 0; i < depth; i++) {
			int layersize = (1 << (depth - i));
			int aindex = (1 << i) + a;
			int bindex = (1 << i) + b;
			int na, nb;
			//cout << a << " " << b << " " << a * layersize + layersize / 2 << " " << b * layersize + layersize / 2<< "\n";
			propagate(aindex, i);
			propagate(bindex, i);
			if(a * layersize + layersize / 2 <= begin) {
				//cout << "r";
				// branch right
				na = 2 * a + 1;
			}
			else {
				//cout << "l";
				// branch left
				na = 2 * a;
				if(a != b) {
					propagate(aindex * 2 + 1, i + 1);
					ret += hash[aindex * 2 + 1];
				}
			}
			if(b * layersize + layersize / 2 <= end) {
				//cout << "r";
				// branch right
				nb = 2 * b + 1;
				if(a != b) {
					propagate(bindex * 2, i + 1);
					ret += hash[bindex * 2];
				}
			}
			else {
				//cout << "l";
				// branch left
				nb = 2 * b;
			}
			//cout << "\n";
			a = na;
			b = nb;
		}

		int aindex = (1 << depth) + a;
		int bindex = (1 << depth) + b;
		propagate(aindex, depth);
		propagate(bindex, depth);
		ret += hash[aindex];
		if(a != b)
			ret += hash[bindex];

		return ret % mod;
	}
	void print() {
		//cout << "TREE:\n";
		for(int i = 0; i <= depth; i++) {
			for(int j = 0; j < (1 << i); j++) {
				//cout << hash[(1 << i) + j] << " ";
			}
			//cout << "\n";
		}
		//cout << "\n";
		for(int i = 0; i <= depth; i++) {
			for(int j = 0; j < (1 << i); j++) {
				//cout << (upd[(1 << i) + j] == 0x0 ? '-' : upd[(1 << i) + j]) << " ";
			}
			//cout << "\n";
		}
		//cout << "----------\n";
	}
};

string cross(string& a, string& b) {
	string ret = a;
	for(int i = 0; i < a.size(); i++) {
		if(a[i] == b[i])
			ret[i] = a[i];
		else if (a[i] != 'J' && b[i] != 'J')
			ret[i] = 'J';
		else if (a[i] != 'O' && b[i] != 'O')
			ret[i] = 'O';
		else if (a[i] != 'I' && b[i] != 'I')
			ret[i] = 'I';
	}
	return ret;
}
long long hashs(string& s, int a) {
	long long pow = 1;
	long long ret = 0;
	for(int i = 0; i < s.size(); i++) {
		ret = (ret + (pow * s[i])) % mod;
		pow = (pow * a) % mod;
	}
	return ret;
}
int main() {
	int N, Q;
	vector<string> vect(9);
	cin >> N;
	cin >> vect[0];
	cin >> vect[1];
	cin >> vect[2];
	vect[3] = cross(vect[0], vect[1]);
	vect[4] = cross(vect[0], vect[2]);
	vect[5] = cross(vect[1], vect[2]);
	vect[6] = cross(vect[3], vect[2]);
	vect[7] = cross(vect[4], vect[1]);
	vect[8] = cross(vect[5], vect[0]);
	cin >> Q;
	string ff;
	cin >> ff;
	vector<char> start(N);
	//cout << ff;
	for(int i = 0; i < N; i++) {
		start[i] = ff[i];
	}
	unordered_set<long long> hashes;
	for(string s : vect) {
		hashes.insert(hashs(s, 31));
	}
	SegmentTree tree(N, start, 31);
	long long ret = tree.get(0, N - 1);
	cout << (hashes.find(ret) == hashes.end() ? "No" : "Yes") << "\n";
	for(int i = 0; i < Q; i++) {
		int a, b;
		char ch;
		cin >> a;
		cin >> b;
		cin >> ch;
		a--;
		b--;
		tree.set(a, b, ch);
		long long ret = tree.get(0, N - 1);
		cout << (hashes.find(ret) == hashes.end() ? "No" : "Yes") << "\n";
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...