首页 > 其他分享 >P11230 [CSP-J 2024] 接龙(官方数据)

P11230 [CSP-J 2024] 接龙(官方数据)

时间:2024-11-15 20:43:56浏览次数:3  
标签:10 int P11230 2024 leq 2000 接龙 1000

[CSP-J 2024] 接龙(官方数据)

题目描述

在玩惯了成语接龙之后,小 J 和他的朋友们发明了一个新的接龙规则。

总共有 n n n 个人参与这个接龙游戏,第 i i i 个人会获得一个整数序列 S i S_i Si​ 作为他的词库。

一次游戏分为若干轮,每一轮规则如下:

  • n n n 个人中的某个人 p p p 带着他的词库 S p S_p Sp​ 进行接龙。若这不是游戏的第一轮,那么这一轮进行接龙的人不能与上一轮相同,但可以与上上轮或更往前的轮相同。
  • 接龙的人选择一个长度在 [ 2 , k ] [2, k] [2,k] 的 S p S_p Sp​ 的连续子序列 A A A 作为这一轮的接龙序列,其中 k k k 是给定的常数。若这是游戏的第一轮,那么 A A A 需要以元素 1 1 1 开头,否则 A A A 需要以上一轮的接龙序列的最后一个元素开头。
    • 序列 A A A 是序列 S S S 的连续子序列当且仅当可以通过删除 S S S 的开头和结尾的若干元素(可以不删除)得到 A A A。

为了强调合作,小 J 给了 n n n 个参与游戏的人 q q q 个任务,第 j j j 个任务需要这 n n n 个人进行一次游戏,在这次游戏里进行恰好 r j r_j rj​ 轮接龙,且最后一轮的接龙序列的最后一个元素恰好为 c j c_j cj​。为了保证任务的可行性,小 J 请来你判断这 q q q 个任务是否可以完成的,即是否存在一个可能的游戏过程满足任务条件。

输入格式

本题有多组测试数据。

输入的第一行包含一个正整数 T T T,表示数据组数。

接下来包含 T T T 组数据,每组数据的格式如下:

第一行包含三个整数 n , k , q n, k, q n,k,q,分别表示参与游戏的人数、接龙序列长度上限以及任务个数。

接下来 n n n 行:

第 i i i 行包含 ( l i + 1 ) (l_i + 1) (li​+1) 个整数 l i , S i , 1 , S i , 2 , … , S i , l i l_i, S_{i,1}, S_{i,2}, \dots , S_{i,l_i} li​,Si,1​,Si,2​,…,Si,li​​,其中第一个整数 l i l_i li​ 表示序列 S i S_i Si​ 的长度,接下来 l i l_i li​ 个整数描述序列 S i S_i Si​。

接下来 q q q 行:

第 j j j 行包含两个整数 r j , c j r_j, c_j rj​,cj​,描述一个任务。

输出格式

对于每个任务:输出一行包含一个整数,若任务可以完成输出 1,否则输出 0。

样例 #1

样例输入 #1

1
3 3 7
5 1 2 3 4 1
3 1 2 5
3 5 1 6
1 2
1 4
2 4
3 4
6 6
1 1
7 7

样例输出 #1

1
0
1
0
1
0
0

提示

【样例 1 解释】

在下文中,我们使用 { A i } = { A 1 , A 2 , … , A r } \{A_i\} = \{A_1, A_2, \dots , A_r\} {Ai​}={A1​,A2​,…,Ar​} 表示一轮游戏中所有的接龙序列, { p i } = { p 1 , p 2 , … , p r } \{p_i\} = \{p_1, p_2, \dots , p_r\} {pi​}={p1​,p2​,…,pr​} 表示对应的接龙的人的编号。由于所有字符均为一位数字,为了方便我们直接使用数字字符串表示序列。

  • 对于第一组询问, p 1 = 1 p_1 = 1 p1​=1、 A 1 = 12 A_1 = 12 A1​=12 是一个满足条件的游戏过程。
  • 对于第二组询问,可以证明任务不可完成。注意 p 1 = 1 p_1 = 1 p1​=1、 A 1 = 1234 A_1 = 1234 A1​=1234 不是合法的游戏过程,因为此时 ∣ A 1 ∣ = 4 > k |A_1| = 4 > k ∣A1​∣=4>k。
  • 对于第三组询问, { p i } = { 2 , 1 } \{p_i\} = \{2, 1\} {pi​}={2,1}、 { A i } = { 12 , 234 } \{A_i\} = \{12, 234\} {Ai​}={12,234} 是一个满足条件的游戏过程。
  • 对于第四组询问,可以证明任务不可完成。注意 { p i } = { 2 , 1 , 1 } 、 { A i } = { 12 , 23 , 34 } \{p_i\} = \{2, 1, 1\}、\{A_i\} = \{12, 23, 34\} {pi​}={2,1,1}、{Ai​}={12,23,34} 不是一个合法的游戏过程,因为尽管所有的接龙序列长度均不超过 k k k,但第二轮和第三轮由同一个人接龙,不符合要求。
  • 对于第五组询问, { p i } = { 1 , 2 , 3 , 1 , 2 , 3 } \{p_i\} = \{1, 2, 3, 1, 2, 3\} {pi​}={1,2,3,1,2,3}、 { A i } = { 12 , 25 , 51 , 12 , 25 , 516 } \{A_i\} = \{12, 25, 51, 12, 25, 516\} {Ai​}={12,25,51,12,25,516} 是一个满足条件的游戏过程。
  • 对于第六组询问,可以证明任务不可完成。注意每个接龙序列的长度必须大于等于 2 2 2,因此 A 1 = 1 A_1 = 1 A1​=1 不是一个合法的游戏过程。
  • 对于第七组询问,所有人的词库均不存在字符 7 \tt 7 7,因此任务显然不可完成。

【样例 2】

见选手目录下的 chain/chain2.in 与 chain/chain2.ans。

该样例满足测试点 1 的特殊性质。

【样例 3】

见选手目录下的 chain/chain3.in 与 chain/chain3.ans。

该样例满足测试点 2 的特殊性质。

【样例 4】

见选手目录下的 chain/chain4.in 与 chain/chain4.ans。

该样例满足特殊性质 A,其中前两组测试数据满足 n ≤ 1000 n \leq 1000 n≤1000、 r ≤ 10 r \leq 10 r≤10、单组测试数据内所有词库的长度和 ≤ 2000 \leq 2000 ≤2000、 q ≤ 1000 q \leq 1000 q≤1000。

【样例 5】

见选手目录下的 chain/chain5.in 与 chain/chain5.ans。

该样例满足特殊性质 B,其中前两组测试数据满足 n ≤ 1000 n \leq 1000 n≤1000、 r ≤ 10 r \leq 10 r≤10、单组测试数据内所有词库的长度和 ≤ 2000 \leq 2000 ≤2000、 q ≤ 1000 q \leq 1000 q≤1000。

【样例 6】

见选手目录下的 chain/chain6.in 与 chain/chain6.ans。

该样例满足特殊性质 C,其中前两组测试数据满足 n ≤ 1000 n \leq 1000 n≤1000、 r ≤ 10 r \leq 10 r≤10、单组测试数据内所有词库的长度和 ≤ 2000 \leq 2000 ≤2000、 q ≤ 1000 q \leq 1000 q≤1000。

【数据范围】

对于所有测试数据,保证:

  • 1 ≤ T ≤ 5 1 \leq T \leq 5 1≤T≤5;
  • 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105, 2 ≤ k ≤ 2 × 1 0 5 2 \leq k \leq 2 \times 10^5 2≤k≤2×105, 1 ≤ q ≤ 1 0 5 1 \leq q \leq 10^5 1≤q≤105;
  • 1 ≤ l i ≤ 2 × 1 0 5 1 \leq l_i \leq 2 \times 10^5 1≤li​≤2×105, 1 ≤ S i , j ≤ 2 × 1 0 5 1 \leq S_{i,j} \leq 2 \times 10^5 1≤Si,j​≤2×105;
  • 1 ≤ r j ≤ 1 0 2 1 \leq r_j \leq 10^2 1≤rj​≤102, 1 ≤ c j ≤ 2 × 1 0 5 1 \leq c_j \leq 2 \times 10^5 1≤cj​≤2×105;
  • 设 ∑ l \sum l ∑l 为单组测试数据内所有 l i l_i li​ 的和,则 ∑ l ≤ 2 × 1 0 5 \sum l\leq 2\times 10^5 ∑l≤2×105。
测试点 n ≤ n\leq n≤ r ≤ r\leq r≤ ∑ l ≤ \sum l\leq ∑l≤ q ≤ q\leq q≤特殊性质
1 1 1 1 0 3 10^3 103 1 1 1 2000 2000 2000 1 0 3 10^3 103
2 , 3 2,3 2,3 10 10 10 5 5 5 20 20 20 1 0 2 10^2 102
4 , 5 4,5 4,5 1 0 3 10^3 103 10 10 10 2000 2000 2000 1 0 3 10^3 103A
6 6 6 1 0 5 10^5 105 1 0 2 10^2 102 2 × 1 0 5 2\times 10^5 2×105 1 0 5 10^5 105A
7 , 8 7,8 7,8 1 0 3 10^3 103 10 10 10 2000 2000 2000 1 0 3 10^3 103B
9 , 10 9,10 9,10 1 0 5 10^5 105 1 0 2 10^2 102 2 × 1 0 5 2\times 10^5 2×105 1 0 5 10^5 105B
11 , 12 11,12 11,12 1 0 3 10^3 103 10 10 10 2000 2000 2000 1 0 3 10^3 103C
13 , 14 13,14 13,14 1 0 5 10^5 105 1 0 2 10^2 102 2 × 1 0 5 2\times 10^5 2×105 1 0 5 10^5 105C
15 ∼ 17 15\sim 17 15∼17 1 0 3 10^3 103 10 10 10 2000 2000 2000 1 0 3 10^3 103
18 ∼ 20 18\sim 20 18∼20 1 0 5 10^5 105 1 0 2 10^2 102 2 × 1 0 5 2\times 10^5 2×105 1 0 5 10^5 105

特殊性质 A:保证 k = 2 × 1 0 5 k = 2 \times 10^5 k=2×105。

特殊性质 B:保证 k ≤ 5 k ≤ 5 k≤5。

特殊性质 C:保证在单组测试数据中,任意一个字符在词库中出现次数之和均不超过 5 5 5。

容易发现是图论题,建模就是每个位置往他能接的位置连边,于是不妨先考虑给定一个一般的有向图怎么做。简单的想法是预处理出所有答案,你可以用一个类似广搜的东西,从 111 开始每次向外拓展一层,记录可达性即可,复杂度是 O(nr)O(nr)O(nr) 的。

但是这题的图边数特别多,那我们干脆不建边了,直接去判断每个点能否被当前的点到达。每次记录的就是当前接龙的最后一个数。

题目有个很烦的限制,一个人不能接两次。但是可以发现,如果当前这一层的某个数 xxx 同时在至少两个人的序列里,那么所有人的数 xxx 都能接到下一个了。所以只要考虑只有一个人有 xxx 的情况。开个数组记录这一层的每个数在谁手上,没有为 −1-1−1,有一个人 iii 有就设为 iii,两个人及以上有设为 000。这样处理后就可以快速找出可以接到哪些位置上了。

然后再通过这些新接的头找出所有能接的尾巴。先对所有头打标记,然后遍历每一个位置,如果他距离上一个标记(不含自己)的距离 ≤k\le k≤k 就加入下一层的队列。重复做这个就好了,单组数据复杂度 O(nr+q)O(nr+q)O(nr+q)。

AC 代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;
const int MAXM = 1e2 + 10;
inline 
void read(int &x) {
	x = 0; char c = getchar();
	for (; isspace(c); c = getchar());
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}
int T, n, m, q; int cnt[MAXN]; bool ans[MAXM][MAXN];
int a[MAXN]; bool vis[MAXN]; int pos[MAXN];
inline 
void init() {
	vector<pair<int, int>> f, g;
	for (int i = 1; i <= n; i++) {
		for (int j = pos[i], p = -1e9; j < pos[i + 1]; j++) {
			if (j - p < m) f.emplace_back(i, j), ans[1][a[j]] = 1;
			if (a[j] == 1) p = j;
		}
	}
	for (int t = 2; t <= 100; t++) {
		memset(cnt, 0xff, sizeof cnt);
		for (pair<int, int> x : f) {
			int y = a[x.second];
			if (cnt[y] == -1) cnt[y] = x.first;
			else if (cnt[y] != x.first) cnt[y] = 0;
		}
		for (int i = 1; i <= n; i++) {
			for (int j = pos[i]; j < pos[i + 1]; j++) {
				if (~cnt[a[j]] && cnt[a[j]] != i) g.emplace_back(i, j);
			}
		}
		f.clear();
		for (pair<int, int> x : g) vis[x.second] = 1;
		for (int i = 1; i <= n; i++) {
			for (int j = pos[i], p = -1e9; j < pos[i + 1]; j++) {
				if (j - p < m) f.emplace_back(i, j), ans[t][a[j]] = 1;
				if (vis[j]) p = j;
			}
		}
		for (pair<int, int> x : g) vis[x.second] = 0;
		g.clear();
	}
}
int main() {
	freopen("chain.in", "r", stdin);
	freopen("chain.out", "w", stdout);
	for (read(T); T--; ) {
		read(n), read(m), read(q);
		memset(ans, 0, sizeof ans);
		memset(vis, 0, sizeof vis);
		for (int i = 1, k; i <= n; i++) {
			read(k), pos[i + 1] = pos[i] + k;
			for (int j = pos[i]; j < pos[i + 1]; j++) read(a[j]);
		}
//		clock_t st = clock();
		init();
//		fprintf(stderr, "init time: %.3lfs\n", (double)(clock() - st) / CLOCKS_PER_SEC);
		for (int r, c; q--; read(r), read(c), printf("%d\n", ans[r][c]));
	}
}

思路:

容易发现是动态规划题,状态是 dpk,i,jdp_{k, i, j}dpk,i,j​ 表示在 kkk 轮第 iii 个人是否可以出以第 jjj 张牌结尾的接龙序列,然后考虑状态转移方程:

dpk,i,j=⋁[l≠i&al,p∈Si,j−k+1,j]dpk−1,l,pdp_{k,i,j} = \bigvee [l \ne i \& a_{l,p} \in S_{i, j - k + 1,j}] dp_{k -1, l, p}dpk,i,j​=⋁[l=i&al,p​∈Si,j−k+1,j​]dpk−1,l,p​

其中 Si,l,rS_{i, l, r}Si,l,r​ 表示 ai,l⋯ra_{i, l \cdots r}ai,l⋯r​ 这些数构成的集合。

然后考虑令:

sk,x=∑i=1n∑j=1leni[ai,j=x]dpk,i,jgk,i,x=∑j=1leni[ai,j=x]dpk,i,js_{k, x} = \sum_{i = 1}^n \sum_{j = 1} ^{len_i} [a_{i, j} = x] dp_{k,i,j} \\ g_{k, i, x} = \sum_{j = 1} ^{len_i} [a_{i, j} = x] dp_{k,i,j}sk,x​=i=1∑n​j=1∑leni​​[ai,j​=x]dpk,i,j​gk,i,x​=j=1∑leni​​[ai,j​=x]dpk,i,j​

则状态转移方程优化为:

dpk,i,j=⋁[sk−1,al,p≠gk−1,i,al,p](al,p∈Si,j−k+1,j)dp_{k, i, j} = \bigvee [s_{k - 1, a_{l,p}} \ne g_{k - 1, i, a_{l,p}} ] (a_{l,p} \in S_{i, j - k + 1,j})dpk,i,j​=⋁[sk−1,al,p​​=gk−1,i,al,p​​](al,p​∈Si,j−k+1,j​)

然后可以走指针优化一下,就可以实现 O(1)O(1)O(1) 转移了,时间复杂度为 O(q+nr)O(q + nr)O(q+nr)。

考场代码:

#include<bits/stdc++.h>
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define mkp(x, y) make_pair(x, y)
#define fin(s) freopen(s, "r", stdin)
#define fout(s) freopen(s, "w", stdout)
using namespace std;
typedef long long ll;
const int N  = 2e5 + 10, M = 105;
inline ll read(){
	ll x = 0, f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-')
		  f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9'){
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return x * f;
}
inline void write(ll x){
	if(x < 0){
		putchar('-');
		x = -x;
	}
	if(x < 10){
		putchar('0' + x);
		return ;
	}
	write(x / 10);
	write(x % 10);
	return ;
}
int T, n, m, q, r, c, cnt, Max;
int len[N], h[N], f[N], s[N];
bool F[M][N];
vector<int> a[N], id[N], g[N];
vector<bool> dp[N];
void solve(){
	Max = 0;
	n = read(), m = read(), q = read();
	for(int i = 1; i <= n; ++i){
		cnt = 0;
		a[i].clear(), g[i].clear(), id[i].clear(), dp[i].clear();
		len[i] = read();
		for(int j = 0; j < len[i]; ++j){
			a[i].push_back(read());
			h[++cnt] = a[i][j];
			Max = max(Max, a[i][j]);
		}
		sort(h + 1, h + cnt + 1);
		cnt = unique(h + 1, h + cnt + 1) - (h + 1);
		for(int j = 0; j < len[i]; ++j)
		  id[i].push_back(lower_bound(h + 1, h + cnt + 1, a[i][j]) - (h + 1));
		dp[i].resize(len[i]); 
		g[i].resize(len[i]); 
	}
	for(int i = 1; i <= Max; ++i){
		s[i] = 0;
		for(int j = 1; j <= 100; ++j)
		  F[j][i] = 0;
	}
	for(int i = 1; i <= n; ++i){
		for(int j = 0; j < len[i]; ++j){
			if(j - m >= 0)
			  --f[a[i][j - m]];
			if(j && f[1]){
				F[1][a[i][j]] = dp[i][j] = 1;
				++s[a[i][j]];
				++g[i][id[i][j]];
			}
			++f[a[i][j]];
		}
		for(int j = 0; j < len[i]; ++j)
		  f[a[i][j]] = 0;
	}
	for(int k = 2; k < M; ++k){
		for(int i = 1; i <= n; ++i){
			int sum = 0;
			for(int j = 0; j < len[i]; ++j){
				dp[i][j] = 0;
				if(j - m >= 0){
					--f[a[i][j - m]];
					if(!f[a[i][j - m]]){
						if(s[a[i][j - m]] != g[i][id[i][j - m]])
						  --sum;	
					}
				}
				dp[i][j] = (sum >= 1);
				if(!f[a[i][j]]){
					if(s[a[i][j]] != g[i][id[i][j]])
					  ++sum;
				}
				++f[a[i][j]];
			}
			for(int j = 0; j < len[i]; ++j)
			  f[a[i][j]] = 0;
		}
		for(int i = 0; i < N; ++i)
		  s[i] = 0;
		for(int i = 1; i <= n; ++i){
			for(int j = 0; j < len[i]; ++j)
			  g[i][j] = 0;
			for(int j = 0; j < len[i]; ++j){
				if(dp[i][j]){
					F[k][a[i][j]] = 1;
					++s[a[i][j]];
					++g[i][id[i][j]];
				}
			}
		}
	}
	while(q--){
		r = read(), c = read();
		if(F[r][c])
		  puts("1");
		else
		  puts("0");
	}
}
int main(){
//	fin("chain.in"), fout("chain.out");
	T = read();
	while(T--)
	  solve();
	return 0;
}

标签:10,int,P11230,2024,leq,2000,接龙,1000
From: https://blog.csdn.net/yaosichengalpha/article/details/143806869

相关文章

  • P11233 [CSP-S 2024] 染色(官方数据)
    [CSP-S2024]染色(官方数据)题目描述给定一个长度为nnn的正整数数组AA......
  • NOIP2024加赛5
    喜欢每个包绑一个hack是吧。暴力操作(opt)容易发现答案具有单调性,考虑二分答案。还发现只需要处理\(1\sim\left\lceil\frac{n}{2}\right\rceil\)即可。发现如果\(c_{i}>c_{j}且i<j\),那么选\(j\)肯定更优。有\(\left\lfloor\frac{a}{bc}\right\rfloor=\left\lfloor\frac{\left\l......
  • CSP-J 2024 总结
    这次CSP-J竞赛,是我人生中的第一次,比赛时心中满怀激动,赛后我也期望得知成绩。初赛中的87.5分很是不错,但是复赛中200分有些遗憾。这次复赛一共四道题,前两道都较为简单,我拿了200分,这是应得的。但后面两道题很难,我没有做出来。第三题有点遗憾,我应该拿到10分左右的,但却爆0了,不然一等是......
  • Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解总结
    AtCoderBeginnerContest379Rated:\(770\)A-Cyclic简单模拟。B-Strawberries字符串模拟,substr函数秒了C-Repeating中等模拟。思路:判断是否合法很简单,重点在计算花费。假设我们是\(0\)号点有\(N\)个棋子,然后移动到每个点上,显然花费为\(\frac{N(N+1)}{......
  • 2024美亚杯资格赛
    Emma已经几天没有收到她姐姐Clara的消息了,报警失踪,她焦虑地将手机提交给警察,希望能找到线索。警察将手机交给你进行电子数据取证。你成功提取了Emma手机的镜像。请根据取证结果回答以下问题。1.[单选题]根据Emma_Mobile.zip,Emma和Clara的微信聊天记录,Emma最后到警署报案并......
  • 【Azure App Service】在App Service上关于OpenSSH的CVE2024-6387漏洞解答
    问题描述当OpenSSH的版本低于9.8p1,有漏洞风险: Asecurityregression(CVE-2006-5051)wasdiscoveredinOpenSSH'sserver(sshd).Thereisaraceconditionwhichcanleadsshdtohandlesomesignalsinanunsafemanner.Anunauthenticated,remoteattackerma......
  • 2024.11.15 test
    A一个\(n\timesm\)的矩形已经给出了\(k\)个位置的数,判断是否有方案使得填入非负整数后,每一个\(2\times2\)的子矩形都满足左上+右下=左下+右上。\(n,m,k\le1e5\)。注意到,矩形合法的条件可以转化为对于任意相邻的两列,在每行中,这两列值的差都相同。也就是对于所有行的每......
  • 深入理解 MySQL 大小写敏感性:配置、问题与实践指南20241115
    深入理解MySQL大小写敏感性:配置、问题与实践指南在开发和部署MySQL数据库时,表名的大小写敏感性问题常常被忽略,却可能在跨平台迁移、团队协作或工具兼容性方面引发复杂的故障。本文将结合实际案例,深入探讨MySQL的lower_case_table_names参数,剖析其行为、配置方法以......
  • NOIP2024加赛5
    NOIP2024加赛5题目来源:2023NOIPA层联测31\(T1\)HZTG5777.暴力操作(opt)\(40pts\)先将\(\{a\}\)升序排序。因为\(\left\lfloor\dfrac{\left\lfloor\frac{a}{b}\right\rfloor}{c}\right\rfloor=\left\lfloor\dfrac{a}{bc}\right\rfloor\),先钦定\(......
  • 2024-2025-1 20241401 《计算机基础与程序设计》 第八周学习总结
    班级链接2024计算机基础与程序设计作业要求第八周作业作业目标①功能设计与面向对象设计②面向对象设计过程③面向对象语言三要素④汇编、编译、解释、执行教材学习内容总结《计算机科学概论》第9章面向对象方法:介绍了面向对象(OOD)的基本概念,包括类和对......