QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#864758#5037. 回文Felix720 0ms0kbC++1411.0kb2025-01-20 23:43:402025-01-20 23:43:40

Judging History

你现在查看的是最新测评结果

  • [2025-01-20 23:43:40]
  • 评测
  • 测评结果:0
  • 用时:0ms
  • 内存:0kb
  • [2025-01-20 23:43:40]
  • 提交

answer

/* Good Game, Well Play. */
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-(x)))
using namespace std;

const int N = 200010, P = 131;
const long long mod = 1000000123;
int n, m, B; string s; long long pw[N];

bool Entag = false; int Enl, Enr;
struct Blocks
{
	int bid[N]; long long pre[N], suf[N];
	struct Part
	{
		int l, r; long long val[2];
		vector < long long > hsh[2];
		inline void rebuild()
		{
			for(int op = 0; op <= 1; ++op)
				val[op] = 0, hsh[op].resize(r - l + 3);
			for(int j = l; j <= r; ++j)
			{
				val[0] = (val[0] * P + s[j]) % mod;
				hsh[0][j - l + 1] = val[0];
			}
			for(int j = r; j >= l; --j)
			{
				val[1] = (val[1] * P + s[j]) % mod;
				hsh[1][j - l + 1] = val[1];
			}
		}
	}; Part part[N];
	inline void init_sum()
	{
		for(int i = 1; i <= bid[n]; ++i)
			pre[i] = (pre[i - 1] * pw[part[i].r - part[i].l + 1] + part[i].val[0]) % mod;
		for(int i = bid[n]; i >= 1; --i)
			suf[i] = (suf[i + 1] * pw[part[i].r - part[i].l + 1] + part[i].val[1]) % mod;
	}
	inline long long in_query(int op, int id, int l, int r)
	{
		if(op == 0) return (part[id].hsh[0][r] - part[id].hsh[0][l - 1] * pw[r - l + 1] % mod + mod) % mod;
		else return (part[id].hsh[1][l] - part[id].hsh[1][r + 1] * pw[r - l + 1] % mod + mod) % mod;
	}
	
	inline void _setup()
	{
		B = sqrt(n);
		for(int i = 1; i <= n; ++i) bid[i] = (i - 1) / B + 1;
		for(int i = 1; i <= bid[n]; ++i)
		{
			part[i].l = B * (i - 1) + 1;
			part[i].r = min(B * i, n);
			part[i].rebuild();
		}
		init_sum();
	}
	inline void _modify(int p)
	{
		part[bid[p]].rebuild();
		init_sum();
	}
	inline long long _query(int op, int l, int r)
	{
		if(Entag)
		{
			op ^= 1; swap(l, r);
			l = Enr - (l - Enl);
			r = Enr - (r - Enl);
		}
		if(l > r) return 0;
		if(bid[l] == bid[r]) return in_query(op, bid[l], l - part[bid[l]].l + 1, r - part[bid[l]].l + 1);
		else
		{
			long long res = 0;
			if(op == 0)
			{
				res = in_query(0, bid[l], l - part[bid[l]].l + 1, part[bid[l]].r - part[bid[l]].l + 1);
				if(bid[l] + 1 < bid[r])
				{
					res = res * pw[part[bid[r] - 1].r - part[bid[l]].r] % mod;
					res = (res + (pre[bid[r] - 1] - pre[bid[l]] * pw[part[bid[r] - 1].r - part[bid[l]].r] % mod + mod)) % mod;
				}
				res = res * pw[r - part[bid[r]].l + 1] % mod;
				res = (res + in_query(0, bid[r], 1, r - part[bid[r]].l + 1)) % mod;
			}
			else
			{
				res = in_query(1, bid[r], 1, r - part[bid[r]].l + 1);
				if(bid[l] + 1 < bid[r])
				{
					res = res * pw[part[bid[r] - 1].r - part[bid[l]].r] % mod;
					res = (res + (suf[bid[l] + 1] - suf[bid[r]] * pw[part[bid[r] - 1].r - part[bid[l]].r] % mod + mod)) % mod;
				}
				res = res * pw[part[bid[l]].r - l + 1] % mod;
				res = (res + in_query(1, bid[l], l - part[bid[l]].l + 1, part[bid[l]].r - part[bid[l]].l + 1)) % mod;
			}
			return res;
		}
	}
}; Blocks blocks;

struct Seq
{
	int x, d, l;
	bool operator < (const Seq &w) const {return x < w.x;}
	bool operator > (const Seq &w) const {return x > w.x;}
};
inline vector < Seq > compress(vector < Seq > vec)
{
	sort(vec.begin(), vec.end());
//	cerr << "+++++++++++++++++++++++++++++++++++++++\n";
//	for(Seq sq : vec) cerr << "org " << sq.x << " " << sq.d << " " << sq.l << '\n';
	vector < Seq > res;
	for(Seq sq : vec)
	{
		if(!res.empty())
		{
			if(res.back().l == 1 && sq.l == 1)
				res.back().d = sq.x - res.back().x, ++res.back().l;
			else if(res.back().l == 1 && sq.x - res.back().x == sq.d)
				res.back().d = sq.d, res.back().l += sq.l;
			else if(sq.l == 1 && sq.x - (res.back().x + res.back().d * (res.back().l - 1)) == res.back().d)
				++res.back().l;
			else if(res.back().l > 1 && sq.l > 1 && res.back().d == sq.d && sq.x - (res.back().x + res.back().d * (res.back().l - 1)) == res.back().d)
				res.back().l += sq.l;
			else res.push_back(sq);
		}
		else res.push_back(sq);
	}
//	for(Seq sq : res) cerr << "final " << sq.x << " " << sq.d << " " << sq.l << '\n';
	return res;
}
struct Data
{
	int l, r;
	vector < Seq > pr, su;
	inline void unit(int p)
	{
		l = r = p;
		pr.clear(); su.clear();
		pr.push_back({1, 1, 1});
		su.push_back({1, 1, 1});
	}
	inline void reset(int ln, int rn)
	{l = ln, r = rn, pr.clear(), su.clear();}
	inline void debug()
	{
		cerr << "pr : ";
		for(Seq sq : pr) cerr << "(" << sq.x << "," << sq.d << "," << sq.l << ") ";
		cerr << '\n';
		cerr << "su : ";
		for(Seq sq : su) cerr << "(" << sq.x << "," << sq.d << "," << sq.l << ") ";
		cerr << '\n';
	}
};
const bool Enop[5] = {false, true, true, true, true};
inline void work(Data u, Data v, int l, int mid, int r, Data &res)
{
//	cerr << "work " << l << " " << mid << " " << r << '\n';
//	for(int i = l; i <= r; ++i) cerr << s[i]; cerr << '\n';
//	u.debug(); cerr << '\n'; v.debug();
	// Case I
	if(Enop[1])
	{
		res.su = v.su;
	}
	// Case II
	if(Enop[2])
	{
		for(Seq sq : v.pr)
		{
//			cerr << "! " << sq.x << " " << sq.d << " " << sq.l << '\n';
			if(sq.l == 1)
			{
				if(sq.x != r - mid && l <= mid - (r - mid - sq.x) + 1 && blocks._query(0, mid + sq.x + 1, r) == blocks._query(1, mid - (r - mid - sq.x) + 1, mid))
					res.su.push_back({sq.x + 2 * (r - mid - sq.x), 1, 1});
			}
			else
			{
				int ex = r - mid - (sq.x + sq.d * (sq.l - 1));
				if(!ex || blocks._query(0, mid + sq.x + sq.d * (sq.l - 1) + 1, r) == blocks._query(0, mid + sq.x + 1, mid + sq.x + (r - mid - sq.x - sq.d * (sq.l - 1))))
				{
					int head = (ex ? 0 : 1), tail = sq.l - 1, lim = -1;
					while(head <= tail)
					{
						int md = (head + tail) >> 1;
						if(l <= mid - (md * sq.d + ex) + 1 && blocks._query(0, r - (md * sq.d + ex) + 1, r) == blocks._query(1, mid - (md * sq.d + ex) + 1, mid))
							lim = md, head = md + 1;
						else tail = md - 1;
					}
					if(lim != -1)
					{
//						cerr << "lim " << lim << '\n';
						if(ex) res.su.push_back({(r - mid) + ex, sq.d, lim + 1});
						else res.su.push_back({(r - mid) + sq.d, sq.d, lim});
					}
				}
				else
				{
					int head = 1, tail = sq.l - 1, lim = 0;
					while(head <= tail)
					{
						int md = (head + tail) >> 1;
						if(l <= mid - md * sq.d + 1 && blocks._query(1, mid - md * sq.d + 1, mid) == blocks._query(0, mid + sq.x + 1, mid + sq.x + md * sq.d))
							lim = md, head = md + 1;
						else tail = md - 1;
					}
					if(l <= mid - lim * sq.d - ex + 1 && blocks._query(1, mid - lim * sq.d - ex + 1, mid) == blocks._query(0, r - (lim * sq.d + ex) + 1, r))
						res.su.push_back({r - mid + lim * sq.d + ex, 1, 1});
				}
			}
		}
	}
	// Case III
	if(Enop[3])
	{
		if(r - mid <= mid - l + 1)
		{
			if(blocks._query(0, mid + 1, r) == blocks._query(1, mid - (r - mid) + 1, mid))
				res.su.push_back({2 * (r - mid), 1, 1});
		}
	}
	// Case IV
	if(Enop[4])
	{
		for(Seq sq : u.su)
		{
			if(sq.l == 1)
			{
				if(l <= mid - sq.x - (r - mid) + 1 && blocks._query(0, mid + 1, r) == blocks._query(1, mid - sq.x - (r - mid) + 1, mid - sq.x))
					res.su.push_back({sq.x + 2 * (r - mid), 1, 1});
			}
			else
			{
				if(mid - sq.x - (r - mid) + 1 < l) continue;
				int head = 1, tail = (sq.l - 1) * sq.d, lim = 0;
				while(head <= tail)
				{
					int md = (head + tail) >> 1;
					if(mid + md <= r && blocks._query(0, mid + 1, mid + md) == blocks._query(1, mid - sq.x - md + 1, mid - sq.x))
						lim = md, head = md + 1;
					else tail = md - 1;
				}
				if(lim == r - mid)
				{
					head = 0, tail = sq.l - 1, lim = -1;
					while(head <= tail)
					{
						int md = (head + tail) >> 1;
						if(l <= mid - sq.x - md * sq.d - (r - mid) + 1 && blocks._query(0, mid - sq.x - md * sq.d - (r - mid) + 1, mid - sq.x - md * sq.d) == blocks._query(1, mid + 1, r))
							lim = md, head = md + 1;
						else tail = md - 1;
					}
					if(lim != -1) res.su.push_back({sq.x + 2 * (r - mid), sq.d, lim + 1});
				}
				else
				{
					head = 0, tail = sq.l - 1, lim = 0;
					while(head <= tail)
					{
						int md = (head + tail) >> 1;
						if(mid + md * sq.d <= r && blocks._query(0, mid - sq.x - sq.d * md + 1, mid - sq.x) == blocks._query(1, mid + 1, mid + sq.d * md))
							lim = md, head = md + 1;
						else tail = md - 1;
					}
					lim *= sq.d;
					if(l <= mid - sq.x - sq.d * (sq.l - 1) - (r - mid - lim) + 1)
					{
						if(blocks._query(0, mid - sq.x - sq.d * (sq.l - 1) - (r - mid - lim) + 1, r) == blocks._query(1, mid - sq.x - sq.d * (sq.l - 1) - (r - mid - lim) + 1, r))
							res.su.push_back({sq.x + (sq.d * (sq.l - 1) - lim) + (r - mid) * 2, 1, 1});
					}
				}
			}
		}
	}
}
Data operator + (Data u, Data v)
{
	int l = u.l, mid = u.r, r = v.r;
	Data res; res.reset(l, r);
	
	// -------------- Suffix --------------
	Entag = false; work(u, v, l, mid, r, res);
	// -------------- Prefix --------------
	Entag = true; Enl = l, Enr = r;
	swap(u, v);
	swap(res.pr, res.su), swap(u.pr, u.su), swap(v.pr, v.su);
	work(u, v, l, r - (mid - l) - 1, r, res);
	swap(res.pr, res.su), swap(u.pr, u.su), swap(v.pr, v.su);
	swap(u, v);
	res.pr = compress(res.pr); res.su = compress(res.su);
	return res;
}
struct SegTree
{
	int rt, idx;
	struct SGT
	{
		int ls, rs; Data data;
		#define ls(x) tree[x].ls
		#define rs(x) tree[x].rs
		#define data(x) tree[x].data
	} tree[N * 2];
	inline void pushup(int now)
	{data(now) = data(ls(now)) + data(rs(now));}
	inline void build(int &now, int l, int r)
	{
		now = ++idx;
		if(l == r) {data(now).unit(l); return ;}
		int mid = (l + r) >> 1;
		build(ls(now), l, mid), build(rs(now), mid + 1, r);
		pushup(now);
//		cerr << "build " << l << " " << r << " ++++++++++++++++++++++++++++++++++++++\n";
//		data(now).debug();
	}
	inline void modify(int now, int l, int r, int pos)
	{
		if(l == r) return ;
		int mid = (l + r) >> 1;
		if(pos <= mid) modify(ls(now), l, mid, pos);
		else modify(rs(now), mid + 1, r, pos);
		pushup(now);
	}
	inline Data query(int now, int l, int r, int L, int R)
	{
		if(L <= l && r <= R) return data(now);
		int mid = (l + r) >> 1;
		Data res;
		if(R <= mid) res = query(ls(now), l, mid, L, R);
		else if(mid < L) res = query(rs(now), mid + 1, r, L, R);
		else res = (query(ls(now), l, mid, L, R) + query(rs(now), mid + 1, r, L, R));
//		cerr << "query " << l << " " << r << " ++++++++++++++++++++\n";
//		res.debug();
		return res;
	}
	
	inline void _init() {build(rt, 1, n);}
	inline void _modify(int p) {modify(rt, 1, n, p);}
	inline Data _query(int l, int r) {return query(rt, 1, n, l, r);}
}; SegTree sgt;

int main()
{
	freopen("text.in", "r", stdin);
	freopen("prog.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> s; n = s.length(); s = ' ' + s;
	pw[0] = 1; for(int i = 1; i <= n; ++i) pw[i] = (__int128)pw[i - 1] * P % mod;
	blocks._setup(); sgt._init();
	cin >> m;
	for(int i = 1, lst = 0; i <= m; ++i)
	{
		int opt, l, r, p; char c; cin >> opt;
		if(opt == 1)
		{
			cin >> p >> c;
//			p ^= lst;
			s[p] = c; blocks._modify(p), sgt._modify(p);
		}
		else
		{
			cin >> l >> r;
//			l ^= lst, r ^= lst;
			lst = 0; Data dt = sgt._query(l, r);
			for(Seq sq : dt.su) lst += sq.l;
			cout << lst << '\n';
		}
	}
	return 0;
}
/*
abbaaabaac
1
2 1 7
*/

Details

Tip: Click on the bar to expand more detailed information

Subtask #1:

score: 0
Dangerous Syscalls

Test #1:

score: 0
Dangerous Syscalls

input:

aabbbabbbaaaaaaabbabbbaaaabaaaabbaabbaabbaaababbbabbbbabbbbaaaabbbabbbbbaaabbbabbaaaaabbbbbaaababbabbaaaaabaabbbbaaababaaabbaabbabbbabbbbaaaaabbbbbbbabbbaabbbabbabbbababbabbbbaaaaabbaababbbbaabbaaaaaabaaabbbaaababbbbaabaaaaababababbbbbbaaaabbbbaaababaaabbaabbbbbaaaabbaaaabaaaaaababbababaaaabaaababaa...

output:


result:


Subtask #2:

score: 0
Dangerous Syscalls

Test #15:

score: 0
Dangerous Syscalls

input:

aabababbabbbbbbabbababaaaabababbabbbbbbabbababaaaabababbabbbbbbabbababaaaabababbabbbbbbabbababaabbbaaabbaabbbbaabbaaabbbaabababbabbbbbbabbababaaaabababbabbbbbbabbababaaaabababbabbbbbbabbababaaaabababbabbbbbbabbababaabbaaabaaaaaabaaabbaabababbabbbbbbabbababaaaabababbabbbbbbabbababaaaabababbabbbbbbabb...

output:


result:


Subtask #3:

score: 0
Dangerous Syscalls

Test #21:

score: 0
Dangerous Syscalls

input:

abbaaaabbabaaaaaabaabbaabbababbaaabbabbbabaabaabaaaaabaabbbbabbabbabbbababbbababababbbbabaabbaaababbbbbababbbbaabbbaaabaababababaabbbbbbaababaabbaaabaabbaaababbabbabbbbaaaaabaaabbbabbbbbbabbbabbabaabbbbbbbaaaabbaaaababbbaaaaaaababaabbbbaaabaaabbaabbbbbbababbaabbaaabbabbbbbabaababbaabaaaabbbbabababba...

output:


result:


Subtask #4:

score: 0
Dangerous Syscalls

Test #27:

score: 0
Dangerous Syscalls

input:

babbaaabbbbbbbabbbababaabbbbbababababbaabaabbbbbbabbbbbbbbbbababbbbabbaabbbaabaabbabbbaabbabbbabbababaababbbabbbbaabbabbabbaaaabbbaaabbbbaabbaaaaaaabbbabbbaaabaababaaabaaaabaaaababaaaaababaaaabaabbaaaabbbabbaabaabbbabbbbbaaabaababbbaaaaabbbbaaabbbbaabbabbbbabbbabbaaaaabaabaaaabbbabbbbbaabbbbabbbbaab...

output:


result:


Subtask #5:

score: 0
Skipped

Dependency #1:

0%

Subtask #6:

score: 0
Skipped

Dependency #1:

0%