2023年女生专场

赛时我们写出来了5题,第一个签到题k,队友看完直接出了;第二个题A题,我们在这个题上浪费了太多的时间了,由于移动的时候,原来的状态和移动后的状态没有处理好,wa掉2发,好在后面想明白了;第三个题f,我看完直接出思路1发a了,写出来的时候手都是抖的,感觉心脏快要跳出来了;第四个题,两个队友算了算时间,发现可以暴力解决,我就开始敲,也是1发a了;第五个题,看了看题,我直接想到用队列,于是队友开始敲,但是看错题,我们以为是A类的一个能量值,B类的一个能量值,痛wa一发;第6个题,当时队友想到了用kmpAC自动机,但是敲完发现结果不对,于是我就想了直接用暴力解决,因为时间太紧(提交的时候是在离结束还有13秒),只用了暴力,很遗憾超时了,但当时想到可以用字典树优化,但是由于时间没能写成,如果写了,我们就6题啦6题!太痛心啦

K. RSP

签到题 队友看出来的   1/n

A. 疾羽的救赎

大模拟,特别要注意移动前和移动后

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<math.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int t, a, b, c, a1, b1, c1;
signed main() {
	cin >> t;
	while (t--) {
		a1 = 2, b1 = 3, c1 = 4;
		a = b = c = 1;
		for (int i = 1; i <= 12; i++) {
//			cout << a1 << " " << b1 << " " << c1 << " " << a << " " << b << " " << c << endl;
			int x, y;
			cin >> x >> y;
			if (x == 1) { //表示a
				if (a == 1) { //表示在最上面的一层;
					if (a1 == b1)b--;
					if (a1 == c1)c--;
					a1 += y; //移动后的位置;
					if (a1 == b1)b += 1; //移动后的位置重合;
					if (a1 == c1)c += 1;
				} else if (a == 2) {
					if (a1 == b1 && b == 1) { //表示没移动之前b在a上面;
						if (a1 == c1)c -= 2;
						a1 += y;
						b1 += y;
						if (a1 == c1)c += 2;
					} else if (a1 == c1 && c == 1) {
						if (a1 == b1)b -= 2;
						a1 += y;
						c1 += y;
						if (a1 == b1)b = 3;
					}
				} else {
					a1 += y;
					b1 += y;
					c1 += y;
				}
			} else if (x == 2) {
				if (b == 1) { //表示在最上面的一层;
					if (b1 == a1)a--;
					if (b1 == c1)c--;
					b1 += y; //移动后的位置;
					if (b1 == a1)a += 1; //移动后的位置重合;
					if (b1 == c1)c += 1;
				} else if (b == 2) {
					if (a1 == b1 && a == 1) { //表示没移动之前a在b上面;
//						cout<<"==="<<a1<<" "<<b1<<" "<<c1<<endl;
						if (b1 == c1)c -= 2;
						a1 += y;
						b1 += y;
						if (b1 == c1)c += 2;
					} else if (b1 == c1 && c == 1) {
						if (a1 == b1)a -= 2;
						b1 += y;
						c1 += y;
						if (a1 == b1)a = 3;
					}
				} else {
					a1 += y;
					b1 += y;
					c1 += y;
				}
			} else {
				if (c == 1) { //表示在最上面的一层;
					if (c1 == a1)a--;
					if (c1 == b1)b--;
					c1 += y; //移动后的位置;
					if (c1 == b1)b += 1; //移动后的位置重合;
					if (a1 == c1)a += 1;
				} else if (c == 2) {
					if (c1 == b1 && b == 1) { //表示没移动之前b在c上面;
						if (a1 == c1)a -= 2;
						c1 += y;
						b1 += y;
						if (a1 == c1)a += 2;
					} else if (a1 == c1 && a == 1) {
						if (a1 == b1)b -= 2;
						a1 += y;
						c1 += y;
						if (a1 == b1)b = 3;
					}
				} else {
					a1 += y;
					b1 += y;
					c1 += y;
				}
			}
		}
//		cout << a1 << " " << b1 << " " << c1 << endl;
		if (a1 == 9 && b1 == 9 && c1 == 9)
			cout << "Y" << endl;
		else
			cout << "N" << endl;
	}
	return 0;
}

F. 最长上升子序列

不存在时的情况为当前位置i(1<=i<=n)前面的最大长度+1比我当前位置的小;

其他的情况都存在,这时我们为了避免重复加上长度我们倒着存.

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<math.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int n;
int a[N], b[N], c[N], d[N];
signed main() {
	scanf("%lld", &n);
	int maxx = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
		b[a[i]]++;//表示每个数出现多少个;
	}
	int flag = 0;
	for (int i = 1; i <= n; i++) { //看看当前的存不存在;
		if (a[i] > (maxx + 1)) {
			flag = 1;
			break;
		}
		if (a[i] > maxx)
			maxx = a[i];
	}
	if (flag == 1)
		printf("-1");
	else {
		for (int i = 1; i <= maxx; i++)//存下每个数从谁开始
			c[i] = c[i - 1] + b[i];
		for (int i = 1; i <= n; i++)//倒着存上
			d[i] = c[a[i]]--;
		for (int i = 1; i <= n; i++)
			printf("%lld ", d[i]);
	}
	return 0;
}

L. 养成游戏

暴力O((6^9)*100)

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<math.h>
#define int long long
using namespace std;
const int N = 1e3 + 10;
int n, m, k;
int d[N], c[N][N];
signed main() {
	scanf("%lld%lld%lld", &n, &m, &k);
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= 7; j++)
			scanf("%lld", &c[i][j]);
	}
	int ans = 0;
	for (int i1 = 0; i1 <= k; i1++) {
		for (int i2 = 0; i2 <= k; i2++) {
			for (int i3 = 0; i3 <= k; i3++) {
				for (int i4 = 0; i4 <= k; i4++) {
					for (int i5 = 0; i5 <= k; i5++) {
						for (int i6 = 0; i6 <= k; i6++) {
							int num = 0;
							d[1] = i1, d[2] = i2, d[3] = i3;
							d[4] = i4, d[5] = i5, d[6] = i6;
							for (int j = 1; j <= m; j++) {
								int s = d[c[j][1]] * c[j][4] + d[c[j][2]] * c[j][5];
								if (c[j][3] == 0) {
									if (s <= c[j][6])
										num += c[j][7];
								} else {
									if (s >= c[j][6])
										num += c[j][7];
								}
							}
							if (num > ans)
								ans = num;
						}
					}
				}
			}
		}
	}
	printf("%lld", ans);
	return 0;
}

G. 精灵宝可梦对战

大模拟,利用单调队列,总共比试k场,所以我们就进行模拟k场

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<math.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, m, k;
queue<int>xx;
queue<int>yy;
struct cs {
	int h, a, b, c, d, e, w, e1;
} x[N], y[N];
signed main() {
	scanf("%lld%lld%lld", &n, &m, &k);
	for (int i = 1; i <= n; i++) {
		xx.push(i);
		x[i].e1 = 0;
		scanf("%lld%lld%lld%lld%lld%lld%lld", &x[i].h, &x[i].a, &x[i].b, &x[i].c, &x[i].d, &x[i].e, &x[i].w);
	}
	for (int i = 1; i <= m; i++) {
		yy.push(i);
		y[i].e1 = 0;
		scanf("%lld%lld%lld%lld%lld%lld%lld", &y[i].h, &y[i].a, &y[i].b, &y[i].c, &y[i].d, &y[i].e, &y[i].w);
	}
	int flag = 0;
	while (k--) {
		int num = 0;
		int i = xx.front();
		xx.pop();
		int j = yy.front();
		yy.pop();
		if ((x[i].a - y[j].c) > num)
			num = (x[i].a - y[j].c);
		if ((x[i].b - y[j].d) > num)
			num = (x[i].b - y[j].d);
		if (x[i].e1 >= x[i].e) {
			if (num < x[i].w) {
				num = x[i].w;
				x[i].e1 -= x[i].e;
			} else
				x[i].e1 += 1;
		} else x[i].e1 += 1;
		xx.push(i);//打完就跑;
		i = xx.front();
		if (num < y[j].h)
			y[j].h -= num;
		else { //表示打死了
			if (yy.empty() == 1) { //变为空了
				printf("Alice");
				flag = 1;
				break;
			} else {
				j = yy.front();
				yy.pop();
			}
		}
		num = 0;
		if ((y[j].a - x[i].c) > num)num = (y[j].a - x[i].c);
		if ((y[j].b - x[i].d) > num)num = (y[j].b - x[i].d);
		if (y[j].e1 >= y[j].e) {
			if (num < y[j].w) {
				num = y[j].w;
				y[j].e1 -= y[j].e;
			} else
				y[j].e1 += 1;
		} else y[j].e1 += 1;
		yy.push(j);//打完就跑;
		if (num < x[i].h)
			x[i].h -= num;
		else {
			xx.pop();
			if (xx.empty() == 1) {
				printf("Bob");
				flag = 1;
				break;
			}
		}
	}
	if (flag == 0)
		printf("Draw");
	return 0;
}

H. 字符串游戏

先将小 A的字符串存到字典树当中,然后再遍厉小 B的字符串,我们从每一个位置开始重新开始一个字符串,然后我们开始查询后面的每一个位置结束的字符串,如果没有以当前位置结束的字符串,那么后面也就没油可以存在的了(当然没有的情况是没有出现当前的字符,另一种情况就是没有以当前位置结束的,但是后面在填几个的存在的)

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<math.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int mod = 1e9 + 7;
int n, m;
string s[N], t[N];
int son[N][50], idx, cnt[N];
void add(string ss) {
	int p = 0;
	for (int i = 0; ss[i]; i++) {
		int u = ss[i] - 'a';
		if (son[p][u] == 0)
			son[p][u] = ++idx;
		p = son[p][u];
	}
	cnt[p] += 1;
}
int query(string ss) {
	int p = 0;
	for (int i = 0; ss[i]; i++) {
		int u = ss[i] - 'a';
		if (son[p][u] == 0)return -1;
		p = son[p][u];
	}
	return cnt[p];
}
signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {//存 
		cin >> s[i];
		add(s[i]);
	}

	for (int i = 1; i <= m; i++) {
		int ans = 0;
		cin >> t[i];
		int tt = t[i].size();
		for (int j = 0; j < tt; j++) {//以当前位置开始 
			string l = "";
			for (int k = j; k < tt; k++) {//当前位置结束 
				l += t[i][k];
				int num = query(l);
				if (num == -1)break;//不存在 
				else if (num == 0)continue;//后面填几个存在 
				else {//应当位置结尾的存在; 
					ans = (ans + ((j + 1) * (tt - k)) % mod) % mod; 
				}
			}
		}
		cout << ans << endl;
	}

	return 0;
}

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值