Submission #419885

#TimeUsernameProblemLanguageResultExecution timeMemory
419885BertedCrossing (JOI21_crossing)C++14
100 / 100
609 ms24676 KiB
#include <iostream>
#include <set>
#include <vector>
#define ll long long

using namespace std;

const int Hs = 2, SZ = (1 << 19) + 5;

const char cmp[3] = {'J', 'O', 'I'};
const ll MD[Hs] = {1000000007, 420691273}, Hp[Hs] = {17, 7};
ll pre[Hs][2][200001];

inline int getVal(const char &c)
{
	if (c == 'J') return 1;
	else if (c == 'O') return 2;
	else if (c == 'I') return 3;
	else return -1;
}

struct Hash
{
	int sz = 0; ll A[Hs] = {};
	inline void build(const string &s, const int &l, const int &r)
	{
		sz = r - l + 1;
		for (int i = l; i <= r; i++)
		{
			for (int j = 0; j < Hs; j++) {A[j] = (A[j] * Hp[j] % MD[j] + getVal(s[i])) % MD[j];}
		}
	}
};

inline Hash merge(const Hash &l, const Hash &r)
{
	Hash ret;
	for (int i = 0; i < Hs; i++)
	{
		ret.A[i] = (r.A[i] + l.A[i] * pre[i][0][r.sz]) % MD[i];
		ret.sz = l.sz + r.sz;
	}
	return ret;
}

inline bool operator==(const Hash &l, const Hash &r)
{
	for (int i = 0; i < Hs; i++)
	{
		if (l.A[i] != r.A[i]) return 0;
	}
	return 1;
}

int N, Q;
string A, B, C, T;
set<string> S;
Hash seg[SZ]; int lz[SZ];

void prop(int idx, int L, int R)
{
	if (L <= R)
	{
		if (lz[idx])
		{
			for (int i = 0; i < Hs; i++) {seg[idx].A[i] = pre[i][1][R - L + 1] * lz[idx] % MD[i];}
			if (L < R)
			{
				lz[2 * idx] = lz[idx];
				lz[2 * idx + 1] = lz[idx];
			}
			lz[idx] = 0;
		}
	}
}

void build(int idx, int L, int R, const string &T)
{
	//cerr << "BLD: " << L << " " << R << "\n";
	if (L < R)
	{
		int M = L + R >> 1;
		build(2 * idx, L, M, T);
		build(2 * idx + 1, M + 1, R, T);
		seg[idx] = merge(seg[2 * idx], seg[2 * idx + 1]);
	}
	else if (L == R) {seg[idx].build(T, L, R);}
}

inline void upd(int idx, int L, int R, int l, int r, int t)
{
	l = max(L, l); r = min(R, r);
	prop(idx, L, R);
	if (l <= r)
	{
		if (L == l && R == r) {lz[idx] = t; prop(idx, L, R);}
		else
		{
			int M = L + R >> 1;
			upd(2 * idx, L, M, l, r, t);
			upd(2 * idx + 1, M + 1, R, l, r, t);
			seg[idx] = merge(seg[2 * idx], seg[2 * idx + 1]);
		}
	}
}

inline string cross(const string &A, const string &B)
{
	string ret;
	for (int i = 0; i < N; i++)
	{
		int a = getVal(A[i]) - 1, b = getVal(B[i]) - 1;
		if (a == b) ret.push_back(cmp[a]);
		else ret.push_back(cmp[3 - a - b]);
	}
	return ret;
}

vector<Hash> dat;

int main()
{
	ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> N;
	cin >> A >> B >> C;

	for (int i = 0; i < Hs; i++)		// Hashing precomputation.
	{
		pre[i][0][0] = 1;
		for (int k = 1; k <= N; k++)
		{
			pre[i][0][k] = pre[i][0][k - 1] * Hp[i] % MD[i];
			pre[i][1][k] = (pre[i][1][k - 1] * Hp[i] % MD[i] + 1) % MD[i];
		}
	}

	S.insert(A); S.insert(B); S.insert(C);
	for (const auto &x : S)
		for (const auto &y : S) S.insert(cross(x, y));

	for (const auto &x : S) 
	{
		dat.push_back(Hash());
		dat.back().build(x, 0, N - 1);
		//cerr << x << "\n" << dat.back().A[0] << "\n" << dat.back().A[1] << "\n";
	}

	cin >> Q;
	cin >> T;

	build(1, 0, N - 1, T);

	for (int i = 0; i <= Q; i++)
	{
		bool found = 0;
		for (const auto &x : dat)
		{
			if (x == seg[1]) {found = 1; break;} 
		}
		if (found) cout << "Yes\n";
		else cout << "No\n";
		if (i < Q)
		{
			int l, r; char c; cin >> l >> r >> c;
			upd(1, 0, N - 1, l - 1, r - 1, getVal(c));
		}
	}
	return 0;
}

Compilation message (stderr)

Main.cpp: In function 'void build(int, int, int, const string&)':
Main.cpp:82:13: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   82 |   int M = L + R >> 1;
      |           ~~^~~
Main.cpp: In function 'void upd(int, int, int, int, int, int)':
Main.cpp:99:14: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   99 |    int M = L + R >> 1;
      |            ~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...