赛时我们写出来了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;
}