题解分享
题解分享简介
题解
看到大家都队列模拟,但前缀和也可以吧。代码如下:
```cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
ll a[N], b[N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
ll tmp;
cin >> tmp;
a[i] = a[i - 1] + tmp;
}
for (int i = 1; i <= m; i++)
{
ll tmp;
cin >> tmp;
b[i] = b[i - 1] + tmp;
}
ll res = 0;
int index1 = 1, index2 = 1;
int pre_index1 = 0, pre_index2 = 0;
while (index1 <= n && index2 <= m)
{
if (a[index1] - a[pre_index1] == b[index2] - b[pre_index2])
{
res += index1 + index2 - pre_index1 - pre_index2 - 2;
pre_index1 = index1;
pre_index2 = index2;
index2++;
index1++;
}
else if (a[index1] - a[pre_index1] < b[index2] - b[pre_index2])
{
index1++;
}
else
{
index2++;
}
}
cout << res;
return 0;
}
```
查看全文
1
0
0
5
vector排序——题解
include
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,c,t;
cin>>n;
vector
a[n+1];//创建了n+1个vector对象,也就是一维数组a的每个元素都是vector
for(int i=1;i
>c;//输入数组的大小
while(c--)//利用while循环c次,将对应的数组元素推入每一个数组
{
cin>>t;
a[i].push_back(t);
}
sort(a[i].begin(),a[i].end());//每完成一次就先将当前数组排序
}
sort(a+1,a+n+1);//按字典序对n个数组进行排序,因为数组一旦创建,下标就是从0开始的
//而我们在存数据的时候是从1开始的,所以要使用a+1,至于a+n+1,因为C++的 sort(first, last) 排序范围是 [first, last),
//包含first,不包含last,所以sort的第二个参数要指向最后一个元素的下一个位置,是 a+n+1
for(int i=1;i<=n;i++)
{
for(int j=0;j<a[i].size();j++)
{
cout<<a[i][j]<<" ";//输出数组元素
//i代表是第i组数组,j代表是第i组数组的第j个元素
}
cout<<endl;
}
return 0;
}
查看全文
3
0
0
28
字符串编号——题解
include
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s,t;//定义string类型的变量s和t,s用来输入数字序列,t用来存放后续提取的子串
int sd;//sd用来将提取的数字子串转换为数字,对应上26个字母的下标
cin>>s;
char zm[27]={'0','A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
//创建字母数组,注意A从下标为1的地方开始
for(int i=0;i
=1&&sd<=26)//判断如果数字在1-26之间,那我们可以直接输出这个数字下标对应的字母
{
cout<<zm[sd];
i++;//完成之后i要加1,因为进入这个if条件意味着我们提取的是两位数字字符
//之后for循环里面也还要加1,下一个子串从已经提取过后的剩下的子串的第一位开始提取
}
else//如果提取的两位字符转为数字后超出了字母的下标范围
{
t=s.substr(i,1);//这时我们只提取一位数字字符放入t当中
sd=stoi(t);//将其转换为数字
cout<<zm[sd];//输出其对应下标的字母
}
}
return 0;
}
查看全文
2
0
0
33
分巧克力
```cpp
// 请把代码粘贴在这里
```
include
using namespace std;
int n,k;
int maxn;
int H[100010];
int W[100010];
int l,r,mid;
int sum,ans;
/猜想:二分难道是从11到以小明所拥有的最大巧克力的较小边为边长的正方形,
以1为左端点,以上述正方形的边长为右端点?取mid值,判断是否能切出等大的K块正方形巧克力,
如果可以,则将左指针向右移一位,再取mid,如果不可以,右指针向左移动一位,取mid,
要设置变量ans存储mid值,直到左指针>右指针,最后一次二分ans保留的值,即为最大边长/
/
问题:可最大边一定不行,除非是正方形,并且这n块巧克力必须全这么大,不剪枝吗,等等,难道是担心这两条边之间的边长可能符合要求?
回答:在二分查找里,右边界表示的是:搜索范围的上限,而不是答案可能的最大值
/
bool check(int x) {
//注意:sum要清0
sum=0;
for(int i=0;i
=k) {
return true;
}else{
return false;
}
}
int main() {
cin>>n>>k;
for(int i=0;i
>H[i]>>W[i];
maxn=max(H[i],maxn);
maxn=max(W[i],maxn);
//不断更新最大边,存入maxn
}
l=1;
r=maxn;
while(l<=r) {
mid=(l+r)/2;
if(check(mid)) {
ans=mid;
l=mid+1;
}else {
r=mid-1;
}
}
cout<<ans<<endl;
return 0;
}
查看全文
2
0
0
12
奇怪的电梯
include
include
include
include
using namespace std;
int N, A, B;
vector
K;
vector
visited;
int min_steps = INT_MAX; // 记录全局最优解
void dfs(int current_floor, int steps) {
// 1. 剪枝:如果当前步数已经超过已知最优解,没必要继续
if (steps >= min_steps) {
return;
}
// 2. 结束条件:到达目标
if (current_floor == B) {
min_steps = min(min_steps, steps);
return;
}
// 3. 获取当前楼层的“魔力数字”
int step_size = K[current_floor];
// 如果当前楼层数字为0,无法移动,死胡同
if (step_size == 0) return;
// --- 尝试上升 ---
int next_up = current_floor + step_size;
if (next_up
= 1 && !visited[next_down]) {
visited[next_down] = true; // 标记
dfs(next_down, steps + 1);
visited[next_down] = false; // 回溯
}
}
int main() {
// 输入
cin >> N >> A >> B;
K.resize(N + 1); // 1-based indexing
for (int i = 1; i
> K[i];
}
// 初始化
visited.resize(N + 1, false);
visited[A] = true; // 标记起点已访问
// 开始搜索
dfs(A, 0);
// 输出
if (min_steps == INT_MAX) {
cout << -1 << endl;
} else {
cout << min_steps << endl;
}
return 0;
}
查看全文
2
0
0
20
用map和set的做法
```cpp
// 请把代码粘贴在这里
#include<bits/stdc++.h>
#include<map>
#include<string>
using namespace std;
int main()
{
map<char,int>char_t;
set<char>ss;//去重同次数字母,且自动排序
string line;
int temp=0;
cin>>line;
for(auto &c:line)
{
char_t[c]++;
}
for(auto &p:char_t)
{
temp=max(temp,p.second);
}
for(auto &pi:char_t)
{
if(pi.second==temp)
{
ss.insert(pi.first);
}
}
for(auto &s:ss)
{
cout<<s;
}
}
```
查看全文
1
0
0
22
扫雷
```cpp
// 请把代码粘贴在这里
```
include
using namespace std;
typedef pair
pii;
// 自定义哈希函数,用于 unordered_map 支持 pair
struct HashPair {
size_t operator()(const pii& p) const {
return (size_t)p.first 1000000007 + p.second;
}
};
// 存储:坐标 -> {最大半径, 数量}
unordered_map
, HashPair> mp;
// 记录已引爆的坐标
unordered_set
visited;
int n, m;
int ans = 0;
// 深度优先搜索
void dfs(int x, int y, int r) {
// 扫描正方形范围:[x-r, x+r] [y-r, y+r]
// 题目保证 r
(long long)r r) continue;
// --- 命中 ---
visited.insert(p); // 标记爆炸
ans += mp[p].second; // 累加该坐标的数量
// 递归:用这个新炸的最大半径继续引爆
dfs(i, j, mp[p].first);
}
}
}
int main() {
// 优化 IO
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
// 1. 读入
for (int i = 0; i
> x >> y >> r;
pii p = {x, y};
// 如果同一点有多个,保留数量,半径取最大值
if (mp.count(p)) {
mp[p].second++;
mp[p].first = max(mp[p].first, r);
} else {
mp[p] = {r, 1};
}
}
// 2. 读入火箭并触发 DFS
for (int i = 0; i
> x >> y >> r;
// 火箭也是引爆源,直接开始 DFS
dfs(x, y, r);
}
cout << ans << endl;
return 0;
}
查看全文
1
0
0
14
地宫取宝
```cpp
// 请把代码粘贴在这里
```
include
include
include
// 用于 memset
using namespace std;
const int MOD = 1000000007;
// 题目范围:n,m
= n || y >= m) return 0;
// 2. 到达终点
if (x == n - 1 && y == m - 1) {
long long res = 0;
int current_val = grid[x][y];
int prev_max_val = (max_val_idx == 0) ? -1 : (max_val_idx - 1);
// 情况A:不拿终点的宝物
if (cnt == k) {
res = (res + 1) % MOD;
}
// 情况B:拿终点的宝物 (需满足数量+1=k 且 价值严格大于之前最大值)
if (cnt + 1 == k && current_val > prev_max_val) {
res = (res + 1) % MOD;
}
return res;
}
// 3. 记忆化检查 (如果算过,直接返回)
if (memo[x][y][cnt][max_val_idx] != -1) {
return memo[x][y][cnt][max_val_idx];
}
// 4. 继续搜索
long long ans = 0;
int current_val = grid[x][y];
int prev_max_val = (max_val_idx == 0) ? -1 : (max_val_idx - 1);
// 方向:向下 (x+1, y) 和 向右 (x, y+1)
// 选择1:不拿当前格子的宝物,直接往下走
ans = (ans + dfs(x + 1, y, cnt, max_val_idx)) % MOD;
ans = (ans + dfs(x, y + 1, cnt, max_val_idx)) % MOD;
// 选择2:拿当前格子的宝物 (如果符合条件),然后往下走
if (current_val > prev_max_val && cnt
> n >> m >> k)) return 0;
for (int i = 0; i
> grid[i][j];
}
}
// 初始化 memo 为 -1,表示未计算
memset(memo, -1, sizeof(memo));
// 从 (0,0) 开始,初始数量0,初始最大价值索引0 (代表-1)
cout << dfs(0, 0, 0, 0) << endl;
return 0;
}
查看全文
1
0
0
10
题解
```cpp
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
string s;
if (!(cin >> s)) return 0;
int ans = 0;
int lzone = 0, mzone = 0, szone = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == 'L') lzone++;
else if (s[i] == 'M') mzone++;
else szone++;
}
int lstart = 0, lend = lzone - 1;
int mstart = lzone, mend = lzone + mzone - 1;
int sstart = lzone + mzone, send = (int)s.length() - 1;
int minl = 0, sinl = 0, linm = 0, sinm = 0, lins = 0, mins = 0;
for (int i = lstart; i <= lend; i++) {
if (s[i] == 'M') minl++;
else if (s[i] == 'S') sinl++;
}
for (int i = mstart; i <= mend; i++) {
if (s[i] == 'L') linm++;
else if (s[i] == 'S') sinm++;
}
for (int i = sstart; i <= send; i++) {
if (s[i] == 'M') mins++;
else if (s[i] == 'L') lins++;
}
ans += min(lins, sinl) + min(linm, minl) + min(sinm, mins);
// 每三本形成一个环的书需要两次交换
ans += (abs(lins - sinl) + abs(linm - minl) + abs(sinm - mins)) / 3 * 2;
cout << ans;
return 0;
}
```
本质上就是先按L,M,S分块,本来在对应块里的不用动,优先换互相占了对方位置的书,这样换一次就能使两本书到对应位置,剩下的书每三本成环,每个环要交换两次
查看全文
2
0
0
41



