Submission #670220

#TimeUsernameProblemLanguageResultExecution timeMemory
670220blueCrossing (JOI21_crossing)C++17
100 / 100
347 ms38460 KiB
#include <bits/stdc++.h>
using namespace std;

using vi = vector<int>;
using ll = long long;

const ll mod = 1'000'000'007LL;

const int mx = 200'000;

ll pr[1 + mx];
ll basehash[3][1 + mx];



ll mul(ll a, ll b)
{
	return (a * b) % mod;
}

ll ad(ll a, ll b)
{
	return (a + b) % mod;
}


int N;
vi A, B, C;
vi AB, BC, CA;
vi ABC, BCA, CAB;

int op(int a, int b)
{
	if(a == b)
		return a;
	else
		return 0 + 1 + 2 - a - b;
}

vi op(vi a, vi b)
{
	vi res;
	for(int i = 0; i < N; i++)
		res.push_back(op(a[i], b[i]));
	return res;
}

vi stv(string s)
{
	vi res(N);
	for(int i = 0; i < N; i++)
	{
		if(s[i] == 'J')
			res[i] = 0;
		else if(s[i] == 'O')
			res[i] = 1;
		else
			res[i] = 2;
	}
	return res;
}

ll gethash(vi a)
{
	ll res = 0;
	for(int i = 0; i < N; i++)
		res = ad(res, mul(pr[i], a[i]));
	return res;
}





vi T;


struct segtree
{
	int l;
	int r;

	ll hashval;
	bool homo; //homogenous
	int typ;

	segtree* left = NULL;
	segtree* right = NULL;

	segtree(int L, int R)
	{
		l = L;
		r = R;
		// cerr << "enter " << L << ' ' << R << '\n';
		if(L == R)
		{
			// cerr << "enter if\n";
			hashval = T[L];
			homo = 1;
			typ = T[L];
			// cerr << "check\n";
		}
		else
		{
			int m = (L + R) / 2;
			left = new segtree(L, m);
			right = new segtree(m+1, R);


			hashval = ad(left->hashval, mul(right->hashval, pr[left->r - left->l + 1]));
			homo = 0;
			typ = 0;
		}
		// cerr << "exit " << L << ' ' << R << " with hashval = " << hashval << '\n';
	}

	void update(int L, int R, int C)
	{
		if(R < l || r < L)
			return;
		else if(L <= l && r <= R)
		{
			hashval = basehash[C][r - l + 1];
			homo = 1;
			typ = C;
		}
		else
		{
			if(homo)
			{
				left->update(0, N-1, typ);
				right->update(0, N-1, typ);
			}

			left->update(L, R, C);
			right->update(L, R, C);

			hashval = ad(left->hashval, mul(right->hashval, pr[left->r - left->l + 1]));
			homo = 0;
			typ = 0;
		}

		// cerr << "after update hashval " << L << ' ' << R << " = " << hashval << '\n';
	}

};


// void out(vi a)
// {
// 	for(int u : a)
// 		cerr << u;
// 	cerr << '\n';
// }


int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	cin >> N;

	pr[0] = 1;
	pr[1] = 11;
	for(int i = 2; i <= N; i++)
		pr[i] = mul(pr[1], pr[i-1]);


	basehash[0][0] = basehash[1][0] = basehash[2][0] = 0;
	for(int i = 1; i <= N; i++)
	{
		for(int c = 0; c < 3; c++)
			basehash[c][i] = ad(basehash[c][i-1], mul(pr[i-1], c));
	}


	string a, b, c;
	cin >> a >> b >> c;

	A = stv(a);
	B = stv(b);
	C = stv(c);
	AB = op(A, B);
	BC = op(B, C);
	CA = op(C, A);
	ABC = op(A, BC);
	BCA = op(B, CA);
	CAB = op(C, AB);

	// cerr << A << ' ' << B << ' ' << C << ' ' << AB << ' ' << BC << ' ' << CA << '\n';// << ' ' << ABC << ' ' << BCA << ' ' << CAB << '\n';

	// out(A);
	// out(B);
	// out(C);
	// out(AB);
	// out(BC);
	// out(CA);
	// out(ABC);
	// out(BCA);
	// out(CAB);

	set<ll> goodhash;
	for(vi f : {A, B, C, AB, BC, CA, ABC, BCA, CAB})
	{
		// cerr << "inserting " << gethash(f) << '\n';
		goodhash.insert(gethash(f));
	}

	int Q;
	cin >> Q;

	string t0;
	cin >> t0;

	T = stv(t0);

	// out(T);

	// cerr << "start segtree\n";
	segtree S(0, N-1);
	// cerr << "end segtree\n";

	// cerr << "check hash : " << S.hashval << '\n';

	if(goodhash.find(S.hashval) != goodhash.end())
		cout << "Yes\n";
	else
		cout << "No\n";


	for(int q = 1; q <= Q; q++)
	{
		int L, R, C;
		char c;
		cin >> L >> R >> c;
		L--;
		R--;
		if(c == 'J')
			C = 0;
		else if(c == 'O')
			C = 1;
		else
			C = 2;

		S.update(L, R, C);

		if(goodhash.find(S.hashval) != goodhash.end())
		cout << "Yes\n";
		else
			cout << "No\n";
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...