2024寒假模拟赛一补题报告

一、题目报告

        比赛时,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.柏油马路建设

题目大意

给定多个定值区间,再给出多个询问:给定一个问题区间,问是否可以用任意个定值区间来将这个区间覆盖。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值