CF1830C Hyperregular Bracket Strings

考虑包含与相交的区间。

对于相交的两区间 [l1,r1],[l2,r2][l1,r1],[l2,r2],则只需区间 [l1,l2],[l2,r1],[r1,r2][l1,l2],[l2,r1],[r1,r2] 都合法即可。

对于相互包含的两区间 [l1,r1],[l2,r2][l1,r1],[l2,r2](前区间包含后区间),则只需区间 [l2,r2],[l1,l2][r2,r1][l2,r2],[l1,l2]\cup [r2,r1] 都合法即可。

考虑判断所有条件都满足后,区间的拆分情况。

发现对于相交的,即将 [l2,r1][l2,r1] 从两区间里拆分出来。

对于相互包含的,即将 [l2,r2][l2,r2] 从两区间里拆分出来。

于是考虑哈希判断。

对于条件 [l,r][l,r],对 [l,r][l,r] 进行哈希将其分离出来即可。

对于最后的每个单独区间,我们只需要知道它的长度,开个桶统计即可。

长度为 2n2n 的合法括号序列方案数为卡特兰数第 nn 项。

#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
typedef vector<int> vi;
#define F(i, a, b) for(int i = a; i <= (b); ++i)
#define F2(i, a, b) for(int i = a; i < (b); ++i)
#define dF(i, a, b) for(int i = a; i >= (b); --i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug debug("Passing [%s] in LINS %d\n", __FUNCTION__, __LINE__)
#define pb push_back
#define fi first
#define se second
#define Mry debug("%.3lf MB\n", (&Mbe - &Med) / 1048576.0)
#define Try cerr << 1e3 * clock() / CLOCKS_PER_SEC << " ms\n";
typedef long long ll;
//namespace Fread {const int SIZE = 1 << 17; char buf[SIZE], *S, *T; inline char getchar() {if (S == T) {T = (S = buf) + fread(buf, 1, SIZE, stdin); if (S == T) return '\n';} return *S++;}}
//namespace Fwrite {const int SIZE = 1 << 17; char buf[SIZE], *S = buf, *T = buf + SIZE; inline void flush() {fwrite(buf, 1, S - buf, stdout), S = buf;} inline void putchar(char c) {*S++ = c;if (S == T) flush();} struct NTR {~NTR() {flush();}} ztr;}
//#ifdef ONLINE_JUDGE
//#define getchar Fread::getchar
//#define putchar Fwrite::putchar
//#endif
inline int ri() {
	int x = 0;
	bool t = 0;
	char c = getchar();
	while (c < '0' || c > '9') t |= c == '-', c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return t ? -x : x;
}
inline void wi(int x) {
	if (x < 0) {
		putchar('-'), x = -x;
	}
	if (x > 9) wi(x / 10);
	putchar(x % 10 + 48);
}
inline void wi(int x, char s) {
	wi(x), putchar(s);
}
bool Mbe;
const int mod = 998244353;
const int mod2 = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3f;
const int _ = 3e5 + 5;

int n, m, l[_], r[_], a[_], b[_], f[_];
map<pii, int> mp;
int qpow(int x, int y) {
	int r = 1;
	while(y) {
		if(y & 1) r = 1ll * r * x % mod;
		x = 1ll * x * x % mod, y >>= 1;
	} return r;
}
void solve() {
	mt19937 g(time(0) + rand());
	n = ri(), m = ri();
	F(i, 0, n + 2) a[i] = b[i] = 0; mp.clear();
	F(i, 1, m) l[i] = ri(), r[i] = ri();
	l[++m] = 1, r[m] = n;
	F(i, 1, m) {
		if((r[i] - l[i] + 1) & 1) {
			puts("0"); return;
		}		
		int x = g() % mod;
		a[l[i]] = (a[l[i]] + x) % mod, a[r[i] + 1] = (a[r[i] + 1] + mod - x) % mod;
		x = g() % mod2;
		b[l[i]] = (b[l[i]] + x) % mod2, b[r[i] + 1] = (b[r[i] + 1] + mod2 - x) % mod2;
	}
	F(i, 1, n) {
		a[i] = (a[i] + a[i - 1]) % mod;
		b[i] = (b[i] + b[i - 1]) % mod2;
		mp[make_pair(a[i], b[i])]++;
//		cout << a[i] << ' ';
	}
//	cout << '\n';
//	cout << f[2] << "@@\n";
	int ans = 1;
	for(auto v : mp) {
//		cout << v.se <<"!!\n";
		if(v.se & 1) {
			puts("0"); return;
		}
		ans = 1ll * ans * f[v.se / 2] % mod;
	} wi(ans, '\n');
}
bool Med;
signed main() {
	srand(time(0));
//	Mry;
	f[0] = f[1] = 1;
	F(i, 2, 300002) f[i] = 1ll * f[i - 1] * (4 * i - 2) % mod * qpow(i + 1, mod - 2) % mod;
	int T = ri();
	while(T--) solve();
//	Try;
}
posted @ 2023-05-29 18:40  蒟蒻orz  阅读(2)  评论(0编辑  收藏  举报  来源