题目链接
A题
题面
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int main() {
printf("6\n28\n496\n8128\n33550336\n");
return 0;
}
C题
题面
题意
定义\(F\)函数为斐波那契数列,给你一个\(W\),要你构造一个集合\(S\)使得集合内的元素\(f_i\)满足:
\[
W=\sum_{f_i\in S}F[F[f_i]]
\]
如果不满足输出\(-1\),否则输出字典序最小的一个集合。
思路
对于\(n\)很大的时候我们先将它一直减最大的小于等于\(n\)的斐波那契数,直到\(n\leq20\),然后用二进制来枚举选哪些斐波那契数来凑这个\(n\)。
今年湖南多校对抗赛第一场的一道题和这题很像,题解请戳这里。
对\(java\)和\(python\)不太熟悉,所以代码写的有点挫\(\dots\dots\)
\(java\)代码实现如下
import java.util.*;
import java.math.*;
public class Main {
static BigInteger pw[] = new BigInteger[40];
static BigInteger f[] = new BigInteger[3];
static BigInteger a[][] = new BigInteger[3][3];
public static void mul(BigInteger f[], BigInteger a[][]) {
BigInteger c[] = new BigInteger[3];
for(int i = 0; i < 2; ++i) c[i] = BigInteger.ZERO;
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
c[i] = c[i].add(f[j].multiply(a[j][i]));
}
}
for(int i = 0; i < 2; ++i) f[i] = c[i];
}
public static void mulself(BigInteger a[][]) {
BigInteger c[][] = new BigInteger[3][3];
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
c[i][j] = BigInteger.ZERO;
}
}
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
for(int k = 0; k < 2; ++k) {
c[i][j] = c[i][j].add(a[i][k].multiply(a[k][j]));
}
}
}
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
a[i][j] = c[i][j];
}
}
}
public static void init() {
pw[1] = BigInteger.ONE;
pw[2] = BigInteger.ONE;
for(int i = 3; i <= 30; ++i) {
pw[i] = pw[i-1].add(pw[i-2]);
}
for(int cnt = 1; cnt <= 30; ++cnt) {
if(cnt <= 4) {
if(cnt <= 3) pw[cnt] = BigInteger.ONE;
else pw[cnt] = BigInteger.valueOf(2);
continue;
}
f[0] = BigInteger.ONE;
f[1] = BigInteger.ONE;
a[0][0] = BigInteger.ONE; a[0][1] = BigInteger.ONE;
a[1][0] = BigInteger.ONE; a[1][1] = BigInteger.ZERO;
BigInteger x = pw[cnt];
x = x.subtract(BigInteger.valueOf(2));
while(x.compareTo(BigInteger.ZERO) > 0) {
if(x.mod(BigInteger.valueOf(2)).equals(BigInteger.ONE)) {
mul(f, a);
}
mulself(a);
x = x.divide(BigInteger.valueOf(2));
}
pw[cnt] = f[0];
}
}
public static void main(String[] args) {
init();
Vector<Integer> ans = new Vector<Integer>();
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-- != 0) {
BigInteger n = sc.nextBigInteger();
ans.clear();
int idx = 30, flag = 1;
while(true) {
if(n.compareTo(BigInteger.valueOf(20))<=0) break;
int p = -1;
for(int i = idx; i >= 1; --i) {
if(n.compareTo(pw[i]) >= 0) {
p = i;
break;
}
}
if(p == -1) {
flag = 0;
break;
}
n = n.subtract(pw[p]);
idx = p - 1;
ans.add(p);
if(n.equals(BigInteger.ZERO)) break;
}
if(flag == 0) {
System.out.println(-1);
} else {
if(n.equals(BigInteger.ZERO)) {
int vis = 0;
for(int i = ans.size() - 1; i >= 0; --i) {
if(vis == 1) System.out.print(" ");
vis = 1;
System.out.print(ans.elementAt(i));
}
System.out.println();
} else {
idx = 6;
int tot = 1<<idx, pp = 0;
for(int i = 1; i < tot; ++i) {
BigInteger nw = BigInteger.ZERO;
for(int j = 1; j <= idx; ++j) {
if((i & (1<<(j-1))) > 0) {
nw = nw.add(pw[j]);
}
}
if(n.equals(nw)) {
for(int j = idx; j >= 1; --j) {
if((i & (1<<(j-1))) > 0) {
ans.add(j);
}
}
pp = 1;
break;
}
}
if(pp == 0) System.out.println(-1);
else {
int vis = 0;
for(int i = ans.size() - 1; i >= 0; --i) {
if(vis == 1) System.out.print(" ");
vis = 1;
System.out.print(ans.elementAt(i));
}
System.out.println();
}
}
}
}
sc.close();
}
}
\(python\)代码实现如下
def __mul__(f, a):
c = [0] * 3
for i in range(2):
for j in range(2):
c[i] = c[i] + f[j] * a[j][i]
return c
def __mulself__(a):
c = [[0] * 3 for i in range(3)]
for i in range(2):
for j in range(2):
for k in range(2):
c[i][j] = c[i][j] + a[i][k] * a[k][j]
return c
pw = [0]*36
pw[1] = pw[2] = 1
for i in range(3, 31):
pw[i] = pw[i-1] + pw[i-2]
pw[3] = 1
pw[4] = 2
f = [0] * 3
a = [[0] * 3 for i in range(2)]
for i in range(5, 31):
x = pw[i]
x -= 2
f[0] = f[1] = 1
a[0][0] = a[0][1] = a[1][0] = 1
a[1][1] = 0
while(x > 0):
if(x & 1):
f = __mul__(f, a)
a = __mulself__(a)
x >>= 1
pw[i] = f[0]
T = eval(input())
for icase in range(T):
n = eval(input())
ans = []
idx = 30
flag = 1
while(True):
if(n <= 20):
break;
p = -1
for i in range(idx, 0, -1):
if(n >= pw[i]):
p = i
break
if(p == -1):
flag = 0
break
n -= pw[p]
idx = p - 1
ans.append(p)
if(n == 0):
break;
if(flag == 0):
print(-1)
else:
pp = False
if(n == 0):
pp = True
else:
idx = 6
tot = 1<<idx
pp = False
for i in range(1, tot):
nw = 0
for j in range(1, idx + 1):
if((i & (1<<(j-1))) > 0):
nw += pw[j]
if(n == nw):
for j in range(idx, 0, -1):
if ((i & (1 << (j - 1))) > 0):
ans.append(j)
pp = True
break
if(pp):
ans.sort()
for i in range(len(ans)):
print(ans[i], end="")
if(i != len(ans) - 1):
print(end=" ")
else:
print()
else:
print(-1)
H题
题面
题意
给你一个\(2\times n\)的矩阵,你初始时在\((1,1)\)处,每次移动可以往周围八个方向移动,问你到达右下角的方案数是多少。
思路
我们假设前i-1列都已经求好了方案数,那么\(dp[i][j]\)表示第\(i\)列第\(j\)行的方案数,则\(dp[i][1]=dp[i-1][1]+dp[i-1][2],dp[i][2]=dp[i-1][1]+dp[i-1][2]+dp[i][1]\),因此\(dp[i][2]=2*(dp[i-1][1]+dp[i-1][2])=4\times 3^{i-2}\)。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n;
LL qpow(LL x, int n) {
LL res = 1;
while(n) {
if(n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
int main() {
scanf("%d", &n);
if(n == 1) return printf("1\n") * 0;
printf("%lld\n", 4LL * qpow(3, n - 2) % mod);
return 0;
}
I题
题面
思路
我们先用单调栈来求出以\(a_i\)为区间最小值的左右端点,然后再用线段树来维护前\(i\)个前缀和的最大值和最小值,然后对于每个数进行查询即可。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 5e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n;
stack<int> s;
LL sum[maxn];
int a[maxn], l[maxn], r[maxn];
struct node {
int l, r;
LL mx, mn;
}segtree[maxn<<2];
void push_up(int rt) {
segtree[rt].mx = max(segtree[lson].mx, segtree[rson].mx);
segtree[rt].mn = min(segtree[lson].mn, segtree[rson].mn);
}
void build(int rt, int l, int r) {
segtree[rt].l = l, segtree[rt].r = r;
if(l == r) {
segtree[rt].mx = segtree[rt].mn = sum[l];
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid); build(rson, mid + 1, r);
push_up(rt);
}
LL query(int rt, int l, int r, int op) {
if(segtree[rt].l == l && segtree[rt].r == r) {
if(op == 1) return segtree[rt].mx;
else return segtree[rt].mn;
}
int mid = (segtree[rt].l + segtree[rt].r) >> 1;
if(r <= mid) return query(lson, l, r, op);
else if(l > mid) return query(rson, l, r, op);
else {
if(op == 1) return max(query(lson, l, mid, op), query(rson, mid + 1, r, op));
else return min(query(lson, l, mid, op), query(rson, mid + 1, r, op));
}
}
int main(){
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
l[i] = r[i] = i;
sum[i] = sum[i-1] + a[i];
}
for(int i = 1; i <= n; ++i) {
while(s.size() && a[s.top()] > a[i]) {
r[s.top()] = i - 1;
s.pop();
}
s.push(i);
}
while(s.size()) {
r[s.top()] = n;
s.pop();
}
for(int i = n; i >= 1; --i) {
while(s.size() && a[s.top()] > a[i]) {
l[s.top()] = i + 1;
s.pop();
}
s.push(i);
}
while(s.size()) {
l[s.top()] = 1;
s.pop();
}
build(1, 0, n);
LL ans = -INF, tmp;
for(int i = 1; i <= n; ++i) {
if(a[i] < 0) {
tmp = query(1, i, r[i], 2) - query(1, l[i] - 1, i, 1);
} else {
tmp = query(1, i, r[i], 1) - query(1, l[i]-1, i, 2);
}
ans = max(ans, tmp * a[i]);
}
printf("%lld\n", ans);
return 0;
}
J题
题面
题意
给你一棵有\(n\)个结点的树,问你\(u,v\)之间所有的边权小于等于\(k\)的数量。
思路
主席树板子题。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
vector<int> v;
int n, q, x, y, w, len, cnt, tot;
int head[maxn], root[maxn], fa[maxn][30], deep[maxn];
struct edge {
int v, w, next;
}ed[maxn<<1];
void add(int u, int v, int w) {
ed[tot].v = v;
ed[tot].w = w;
ed[tot].next = head[u];
head[u] = tot++;
}
int getid(int x) {
return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
struct node {
int l, r, sum;
}tree[maxn*40];
void update(int l, int r, int& x, int y, int pos) {
tree[++cnt] = tree[y], tree[cnt].sum++, x = cnt;
if(l == r) return;
int mid = (l + r) >> 1;
if(mid >= pos) update(l, mid, tree[x].l, tree[y].l, pos);
else update(mid + 1, r, tree[x].r, tree[y].r, pos);
}
int query(int l, int r, int x, int y, int pos) {
if(r <= pos) return tree[y].sum - tree[x].sum;
if(l == r) return tree[y].sum - tree[x].sum;
int mid = (l + r) >> 1;
if(pos <= mid) return query(l, mid, tree[x].l, tree[y].l, pos);
else return tree[tree[y].l].sum - tree[tree[x].l].sum + query(mid + 1, r, tree[x].r, tree[y].r, pos);
}
void dfs(int u, int d, int p) {
deep[u] = d;
fa[u][0] = p;
for(int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if(v != p) {
update(1, len, root[v], root[u], getid(ed[i].w));
dfs(v, d + 1, u);
}
}
}
void lca() {
for(int i = 1; i <= n; i++) {
for(int j = 1; (1 << j) <= n; j++) {
fa[i][j] = -1;
}
}
for(int j = 1; (1 << j) <= n; j++) {
for(int i = 1; i <= n; i++) {
if(fa[i][j-1] != -1) {
fa[i][j] = fa[fa[i][j-1]][j-1];
}
}
}
}
int cal(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
int k;
for(k = 0; (1 << (1 + k)) <= deep[u]; k++);
for(int i = k; i >= 0; i--) {
if(deep[u] - (1 << i) >= deep[v]) {
u = fa[u][i];
}
}
if(u == v) return u;
for(int i = k; i >= 0; i--) {
if(fa[u][i] != -1 && fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
struct que {
int u, v, w;
}ask[maxn];
int main() {
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++i) {
head[i] = -1;
}
for(int i = 1; i < n; ++i) {
scanf("%d%d%d", &x, &y, &w);
v.push_back(w);
add(x, y, w); add(y, x, w);
}
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d", &ask[i].u, &ask[i].v, &ask[i].w);
v.push_back(ask[i].w);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
len = v.size();
dfs(1, 1, 0);
lca();
for(int i = 1; i <= q; ++i) {
int p = cal(ask[i].u, ask[i].v);
printf("%d\n", query(1, len, root[p], root[ask[i].u], getid(ask[i].w)) + query(1, len, root[p], root[ask[i].v], getid(ask[i].w)));
}
return 0;
}
K题
题面
题意
首先定义一下函数:
\(f(l,r):\bigoplus a_i(l\leq i \leq r)\)
\(g(l,r):\bigoplus f(x,y)(l\leq x\leq y\leq r)\)
\(w(l,r):\bigoplus g(x,y)(l\leq x\leq y\leq r)\)
给你\(n\)个数,\(q\)次查询,每次查询\(l,r\)间的\(w(l,r)\)的值。
思路
打表找规律即可。
我们首先打表发现:
\[
\text{当}r-l+1\text{为偶数时},g(l,r)=0\\
\text{当}r-l+1\text{为奇数时},g(l,r)=l\bigoplus (l+2)\bigoplus (l+4)\bigoplus\dots
\]
然后就可以用下述代码打出\(w(l,,r)\)的解,最后用前缀和预处理一下就行。
打表代码如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
map<int, int> mp;
int main() {
for(int i = 1; i <= 25; ++i) { //区间长度
mp.clear();
for(int j = 1; j <= i; j += 2) { //g的长度
for(int s = 1; s <= i; ++s) {
if(s + j - 1 > i) break;
for(int k = s; k <= i; k += 2) {
if(k + j - 1 > i) break;
mp[k] ++;
if(mp[k] % 2 == 0) mp[k] = 0;
}
}
}
printf("[%d]:", i);
for(int j = 1; j <= i; ++j) {
if(mp[j]) printf("%d ", j);
}
printf("\n");
}
return 0;
}
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n, q;
int a[maxn];
int sum[4][maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
a[0] = 0;
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for(int i = 0; i < 4; ++i) {
sum[i][i] = a[i];
for(int j = i; j + 4 <= n; j += 4) {
sum[i][j+4] = sum[i][j] ^ a[j+4];
}
}
scanf("%d", &q);
int l, r;
while(q--) {
scanf("%d%d", &l, &r);
int len = r - l + 1;
if(len % 4 == 1) {
int num = l % 4;
int s = 0, t = r;
if(l >= 4) {
s = l - 4;
}
t = l + len / 4 * 4;
if(t > r) t -= 4;
printf("%d\n", sum[num][t] ^ sum[num][s]);
} else if(len % 4 == 3) {
int num = (l + 1) % 4;
int s = 0, t = r;
if(l >= 4) {
s = (l + 1) - 4;
}
t = (l + 1) + len / 4 * 4;
if(t > r) t -= 4;
printf("%d\n", sum[num][t] ^ sum[num][s]);
} else if(len % 4 == 0) {
printf("0\n");
} else {
int num1 = l % 4;
int s1 = 0, t1 = r;
if(l >= 4) {
s1 = l - 4;
}
t1 = l + len / 4 * 4;
if(t1 > r) t1 -= 4;
int num2 = (l + 1) % 4;
int s2 = 0, t2 = r;
if(l >= 4) {
s2 = (l + 1) - 4;
}
t2 = (l + 1) + len / 4 * 4;
if(t2 > r) t2 -= 4;
printf("%d\n", sum[num1][t1] ^ sum[num1][s1] ^ sum[num2][t2] ^ sum[num2][s2]);
}
}
}
return 0;
}
M题
题面
题意
给你一个字符串\(S\),然后\(q\)次查询,每次查询\(T\)串是否在\(S\)的子序列中出现过。
思路
由于这题数据比较水,因此我们可以用二分过,但是正解是序列自动机或者\(dp\)预处理。
二分代码实现如下
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 7;
char s[maxn], t[1010];
vector<int>v[30];
vector<int>::iterator it;
int main() {
scanf ( "%s", s + 1 );
int len = strlen ( s + 1 ), q, x, flag, len1, cnt, i;
for ( i = 1 ; i <= len ; i++ ) {
int x = s[i] - 'a';
v[x].push_back ( i );
}
scanf ( "%d", &q );
while ( q-- ) {
scanf ( "%s", t + 1 );
flag = 0;
len1 = strlen ( t + 1 );
if ( len1 > len ) {
printf ( "NO\n" );
continue;
}
x = t[1] - 'a';
if ( v[x].size() != 0 ) cnt = v[x][0];
else {
printf ( "NO\n" );
continue;
}
for ( i = 2 ; i <= len1 ; i++ ) {
x = t[i] - 'a';
if ( v[x].size() == 0 || v[x].back() <= cnt ) {
flag = 1;
break;
}
it = upper_bound ( v[x].begin(), v[x].end(), cnt );
if ( it == v[x].end() ) {
flag = 1;
break;
}
cnt = ( *it );
}
if ( flag ) printf ( "NO\n" );
else printf ( "YES\n" );
}
return 0;
}