一、题目报告
比赛时,T1 AC,T2暴力+贪心得20分,T3没做0分,T4暴力匹配得40分,总得分160
二、赛中概况
开始先做的T1,推理了大约1h,推理的时间有点长,又花了30min把代码解决了,然后转手做T2。T2写了30min的暴力代码,一直调不对,就先去看T3、T4了。T3看完之后没有什么很好的暴力思路,就先把T4的暴力代码写完了。再次看T2,终于把T2的暴力调对了。
三、解题报告
T1.四位密码
题目大意
给定一个字符串,找出所有的四位子串(不算重复的,可以不连续)
题目解析
思路一:枚举出所有可能的四位字符串,去原字符串中匹配判断即可。
思路二:可将所有位置的字母与后方可选取的字母组成对,再将各个对组合在一起,计算不重复的个数。
正解代码
玄学的思路二代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
// #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for (int(i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod)-2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof(t));
#define DBG cerr << __LINE__ << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define N 100005
#define M 100005
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 1000000009
struct node {
ll num;
ll xu[31];
} sum1[N];
ll sum2[N];
ll sum3[N];
ll nnum[31];
ll word[31];
int main() {
// file("password")
string aa;
cin >> aa;
ll n = aa.size();
string a;
a += aa[0];
ll len = 1;
for (int i = 1; i < n; i++) {
if (aa[i] == aa[i - 1])
len++;
else
len = 1;
if (len <= 4) a += aa[i];
}
n = a.size();
memset(word, -1, sizeof word);
for (int i = 0; i < n; i++) {
ll b = a[i] - 'a' + 1;
if (word[b] == -1) word[b] = i + 1;
}
memset(nnum, -1, sizeof nnum);
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
ll c = a[j - 1] - 'a' + 1;
if (sum1[i].xu[c] == 0) {
sum1[i].xu[c] = j;
sum1[i].num++;
}
}
}
for (int i = n; i >= 1; i--) {
ll ssum = 0;
for (int j = 1; j <= 26; j++) {
if (sum1[i].xu[j] != 0) {
ssum += sum1[sum1[i].xu[j]].num;
}
}
sum2[i] = ssum;
}
for (int i = n; i >= 1; i--) {
ll ssum = 0;
for (int j = 1; j <= 26; j++) {
if (sum1[i].xu[j] != 0) {
ssum += sum2[sum1[i].xu[j]];
}
}
sum3[i] = ssum;
}
ll ans = 0;
for (int i = 1; i <= 26; i++) {
if (word[i] != -1) ans += sum3[word[i]];
}
cout << ans;
return 0;
}
T2.打野
题目大意
给定一个地图,从左上角到右下角之间选取两条路径(只能往下或往右走),第一条路径上可以选取1-3个有权值的点,第二条路径可以选取严格小于第一条路径上选取的最小值的、数量不超过第一条路径数量的0-3个有权值的点,求这些点的最大值。
题目解析
按照第一条路径选取的点的数量分为三类:
① 选取一个点:
第一条路径选取一个点,则第二条路径至多选取一个点,那么最优情况就可以看成地图中的最大值与次大值的和。
② 选取两个点:
可以将两个在同一路径上的点连为一条路(同一路径判定:一个点在另一个点到右下角构成的矩阵之内),去找到两个满足条件的和最大的路径。
③ 选取三个点
与选取两个点的思路类似,可以将三个在同一路径上的点连为一条路(同一路径判定:按照选取两个点的方法判定两次即可),去找到两个满足条件的和最大的路径。
找到了三个方案分别的最大值,比较选取出答案即可。
正解代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
// #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define bug printf("--------\n");
#define enter printf("\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for (int(i) = (a); (i) <= (b); ++(i))
#define inv(x, mod) ppow((x), (mod)-2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof(t));
#define DBG cerr << __LINE__ << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define N 10005
#define M 5000005
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 1000000009
struct node {
ll x, y;
ll sum;
} point[N];
struct node1 {
ll sum;
ll maxx;
ll minn;
} edge_3_w[M], edge_3_z[M], edge_2_w[M], edge_2_z[M];
bool cmp1(node A, node B) {
if (A.x == B.x)return A.y < B.y;
return A.x < B.x;
}
bool cmp2(node1 A, node1 B) {
if (A.minn == B.minn)return A.sum > B.sum;
return A.minn > B.minn;
}
bool cmp3(node1 A, node1 B) {
if (A.maxx == B.maxx)return A.sum > B.sum;
return A.maxx > B.maxx;
}
int main() {
ll n;
ll maxxxx = 0, maxxx = 0;
ll mmap[15][15];
ll cnt = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> mmap[i][j];
point[++cnt].sum = mmap[i][j];
point[cnt].x = i;
point[cnt].y = j;
if (mmap[i][j] > maxxxx) {
maxxx = maxxxx;
maxxxx = mmap[i][j];
}
}
}
ll ans = maxxxx + maxxx;
ll num_3 = 0;
sort(point + 1, point + 1 + cnt, cmp1);
for (int i = 1; i <= cnt; i++) {
for (int j = i + 1; j <= cnt; j++) {
for (int v = j + 1; v <= cnt; v++) {
if (!(point[i].y <= point[j].y && point[j].y <= point[v].y))continue;
++num_3;
edge_3_w[num_3].sum = edge_3_z[num_3].sum = point[i].sum + point[j].sum + point[v].sum;
edge_3_w[num_3].maxx = edge_3_z[num_3].maxx = max(max(point[i].sum, point[j].sum), point[v].sum);
edge_3_w[num_3].minn = edge_3_z[num_3].minn = min(min(point[i].sum, point[j].sum), point[v].sum);
}
}
}
ll num_2 = 0;
for (int i = 1; i <= cnt; i++) {
for (int j = i + 1; j <= cnt; j++) {
for (int v = j + 1; v <= cnt; v++) {
if (!(point[i].y <= point[j].y))continue;
++num_2;
edge_2_w[num_2].sum = edge_2_z[num_2].sum = point[i].sum + point[j].sum;
edge_2_w[num_2].maxx = edge_2_z[num_2].maxx = max(point[i].sum, point[j].sum);
edge_2_w[num_2].minn = edge_2_z[num_2].minn = min(point[i].sum, point[j].sum);
}
}
}
sort(edge_3_w + 1, edge_3_w + 1 + num_3, cmp2);
sort(edge_3_z + 1, edge_3_z + 1 + num_3, cmp3);
sort(edge_2_w + 1, edge_2_w + 1 + num_2, cmp2);
sort(edge_2_z + 1, edge_2_z + 1 + num_2, cmp3);
ll j = 1;
for (int i = 1; i <= num_3; i++) {
while (edge_3_w[i].minn <= edge_3_z[j].maxx && j <= num_3)j++;
while (edge_3_w[i].minn > edge_3_z[j].maxx && j <= num_3) {
ans = max(ans, edge_3_w[i].sum + edge_3_z[j].sum);
j++;
}
}
j = 1;
for (int i = 1; i <= num_2; i++) {
while (edge_2_w[i].minn <= edge_2_z[j].maxx && j <= num_2)j++;
while (edge_2_w[i].minn > edge_2_z[j].maxx && j <= num_2) {
ans = max(ans, edge_2_w[i].sum + edge_2_z[j].sum);
j++;
}
}
cout<<max(ans,edge_3_w[1].sum);
return 0;
}
T3.柏油马路建设
题目大意
给定多个定值区间,再给出多个询问:给定一个问题区间,问是否可以用任意个定值区间来将这个区间覆盖。