题目描述
在玩惯了成语接龙之后,小 J 和他的朋友们发明了一个新的接龙规则。
总共有 nn 个人参与这个接龙游戏,第 ii 个人会获得一个整数序列 SiSi 作为他的词库。
一次游戏分为若干轮,每一轮规则如下:
- nn 个人中的某个人 pp 带着他的词库 SpSp 进行接龙。若这不是游戏的第一轮,那么这一轮进行接龙的人不能与上一轮相同,但可以与上上轮或更往前的轮相同。
- 接龙的人选择一个长度在 [2,k][2,k] 的 SpSp 的连续子序列 AA 作为这一轮的接龙序列,其中 kk 是给定的常数。若这是游戏的第一轮,那么 AA 需要以元素 11 开头,否则 AA 需要以上一轮的接龙序列的最后一个元素开头。
- 序列 AA 是序列 SS 的连续子序列当且仅当可以通过删除 SS 的开头和结尾的若干元素(可以不删除)得到 AA。
为了强调合作,小 J 给了 nn 个参与游戏的人 qq 个任务,第 jj 个任务需要这 nn 个人进行一次游戏,在这次游戏里进行恰好 rjrj 轮接龙,且最后一轮的接龙序列的最后一个元素恰好为 cjcj。为了保证任务的可行性,小 J 请来你判断这 qq 个任务是否可以完成的,即是否存在一个可能的游戏过程满足任务条件。
输入格式
本题有多组测试数据。
输入的第一行包含一个正整数 TT,表示数据组数。
接下来包含 TT 组数据,每组数据的格式如下:
第一行包含三个整数 n,k,qn,k,q,分别表示参与游戏的人数、接龙序列长度上限以及任务个数。
接下来 nn 行:
第 ii 行包含 (li+1)(li+1) 个整数 li,Si,1,Si,2,…,Si,lili,Si,1,Si,2,…,Si,li,其中第一个整数 lili 表示序列 SiSi 的长度,接下来 lili 个整数描述序列 SiSi。
接下来 qq 行:
第 jj 行包含两个整数 rj,cjrj,cj,描述一个任务。
输出格式
对于每个任务:输出一行包含一个整数,若任务可以完成输出 1,否则输出 0。
输入输出样例
输入 #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 解释】
在下文中,我们使用 {Ai}={A1,A2,…,Ar}{Ai}={A1,A2,…,Ar} 表示一轮游戏中所有的接龙序列,{pi}={p1,p2,…,pr}{pi}={p1,p2,…,pr} 表示对应的接龙的人的编号。由于所有字符均为一位数字,为了方便我们直接使用数字字符串表示序列。
- 对于第一组询问,p1=1p1=1、A1=12A1=12 是一个满足条件的游戏过程。
- 对于第二组询问,可以证明任务不可完成。注意 p1=1p1=1、A1=1234A1=1234 不是合法的游戏过程,因为此时 ∣A1∣=4>k∣A1∣=4>k。
- 对于第三组询问,{pi}={2,1}{pi}={2,1}、{Ai}={12,234}{Ai}={12,234} 是一个满足条件的游戏过程。
- 对于第四组询问,可以证明任务不可完成。注意 {pi}={2,1,1}、{Ai}={12,23,34}{pi}={2,1,1}、{Ai}={12,23,34} 不是一个合法的游戏过程,因为尽管所有的接龙序列长度均不超过 kk,但第二轮和第三轮由同一个人接龙,不符合要求。
- 对于第五组询问,{pi}={1,2,3,1,2,3}{pi}={1,2,3,1,2,3}、{Ai}={12,25,51,12,25,516}{Ai}={12,25,51,12,25,516} 是一个满足条件的游戏过程。
- 对于第六组询问,可以证明任务不可完成。注意每个接龙序列的长度必须大于等于 22,因此 A1=1A1=1 不是一个合法的游戏过程。
- 对于第七组询问,所有人的词库均不存在字符 77,因此任务显然不可完成。
【样例 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≤1000n≤1000、r≤10r≤10、单组测试数据内所有词库的长度和 ≤2000≤2000、q≤1000q≤1000。
【样例 5】
见选手目录下的 chain/chain5.in 与 chain/chain5.ans。
该样例满足特殊性质 B,其中前两组测试数据满足 n≤1000n≤1000、r≤10r≤10、单组测试数据内所有词库的长度和 ≤2000≤2000、q≤1000q≤1000。
【样例 6】
见选手目录下的 chain/chain6.in 与 chain/chain6.ans。
该样例满足特殊性质 C,其中前两组测试数据满足 n≤1000n≤1000、r≤10r≤10、单组测试数据内所有词库的长度和 ≤2000≤2000、q≤1000q≤1000。
【数据范围】
对于所有测试数据,保证:
- 1≤T≤51≤T≤5;
- 1≤n≤1051≤n≤105,2≤k≤2×1052≤k≤2×105,1≤q≤1051≤q≤105;
- 1≤li≤2×1051≤li≤2×105,1≤Si,j≤2×1051≤Si,j≤2×105;
- 1≤rj≤1021≤rj≤102,1≤cj≤2×1051≤cj≤2×105;
- 设 ∑l∑l 为单组测试数据内所有 lili 的和,则 ∑l≤2×105∑l≤2×105。
测试点 | n≤n≤ | r≤r≤ | ∑l≤∑l≤ | q≤q≤ | 特殊性质 |
---|---|---|---|---|---|
11 | 103103 | 11 | 20002000 | 103103 | 无 |
2,32,3 | 1010 | 55 | 2020 | 102102 | 无 |
4,54,5 | 103103 | 1010 | 20002000 | 103103 | A |
66 | 105105 | 102102 | 2×1052×105 | 105105 | A |
7,87,8 | 103103 | 1010 | 20002000 | 103103 | B |
9,109,10 | 105105 | 102102 | 2×1052×105 | 105105 | B |
11,1211,12 | 103103 | 1010 | 20002000 | 103103 | C |
13,1413,14 | 105105 | 102102 | 2×1052×105 | 105105 | C |
15∼1715∼17 | 103103 | 1010 | 20002000 | 103103 | 无 |
18∼2018∼20 | 105105 | 102102 | 2×1052×105 | 105105 | 无 |
特殊性质 A:保证 k=2×105k=2×105。
特殊性质 B:保证 k≤5k≤5。
特殊性质 C:保证在单组测试数据中,任意一个字符在词库中出现次数之和均不超过 55。
代码
#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(){
T = read();
while(T--)
solve();
return 0;
}