解题思路:模拟+合并,队列实现
2026-08-11 21:09:07
发布于:浙江
15阅读
0回复
0点赞
这道题思路挺难想的,花了一个小时才想到,想到思路又花了13分钟才写出来

这道题如果直接模拟只能得70分,原因是每一次模拟都要吧整个数组都遍历一遍,所以我们可以定义一个结构体asdf把每个块的起始点(id) , 长度(size) 和水果的种类(x)都存储起来。但如果用数组,在模拟的过程中把长度为零的块去除会很麻烦,所以可以用队列,这样只要pop就好了。但去除后还要把其他的合并,比如[1 1] [0 0] [1 1 1] [0] [1 1] [0 0] -> [1] [0] [1 1] [] [1] [0] -> [1] [0] [1 1 1] [0]不然每一个没合并的你都要枚举,还是会超时。但会有一个问题,如果有多个连续的块要合并只靠这个数组就不够了,所以要再定义一个队列hb(合并)把每一次模拟后的结果存进去,然后进行合并,再放入原来的队列。
q:[1 1] [0 0] [1 1 1] [0] [1 1] [0 0] //逐个快枚举,处理后存进hb里,并把处理过的pop
| | | | | |
hb: [1] [0] [1 1] [] [1] [0] -> [1] [0] [1 1 1] [0]//合并
|
q:[1] [0] [1 1 1] [0]//存入q中,把hb清空
那么要如何枚举呢?
把每一个在q队列里的块都枚举一遍,输出起始点(id)。
在合并时会出现一个问题,合并之后的块的每一个水果的下标不一定是连续的,普通的加1不能正确的输出下标,所以可以定义一个bool类型的数组vis来记录哪一个下标被输出过了,然后for循环找下一个没被输出过的,将新的起始点=下一个没被输出过的下标。然后存入hb中
while(!q.empty()){
asdf qwer = q.front();
q.pop();
qwer.size--;
cout << qwer.id << " ";
vis[qwer.id] = false;
for(int j = qwer.id; j <= n; j++){
if(vis[j]){
qwer.id = j;
break;
}
}
if(qwer.size > 0){
hb.push(qwer);
}
}
那么要如何合并呢?
定义一个asdf类型的变量qwer=hb.front()
然后while循把每一个水果的种类与qwer一样的与qwer合并:把qwer.size 加上这个要合并的长度。
while(!hb.empty()){
asdf qwer = hb.front();
if(qwer.size == 0){
hb.pop();
continue;
}
hb.pop();
while(!hb.empty() && hb.front().x == qwer.x){
qwer.size += hb.front().size;
hb.pop();
}
q.push(qwer);
}
那么这道题的思路就讲完了,满分代码如下
#include<bits/stdc++.h>
using namespace std;
int n;
struct asdf{
int x , id , size;
}a[200005];
queue<asdf> q , hb;
bool vis[200005];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
while(!q.empty()){
q.pop();
}
while(!hb.empty()){
hb.pop();
}
for(int i = 1; i <= n; i++){
cin >> a[i].x;
vis[i] = true;
}
int x = -1;
for(int i = 1; i <= n; i++){
if(a[i].x != x){
asdf p;
p.x = a[i].x;
p.id = i;
int num = 0;
while(i <= n && a[i].x ==a[p.id].x){
num++;
i++;
}
p.size = num;
q.push(p);
i--;
}
}
while(!q.empty()){
while(!q.empty()){
asdf qwer = q.front();
q.pop();
qwer.size--;
cout << qwer.id << " ";
vis[qwer.id] = false;
for(int j = qwer.id; j <= n; j++){
if(vis[j]){
qwer.id = j;
break;
}
}
if(qwer.size > 0){
hb.push(qwer);
}
}
cout << "\n";
while(!hb.empty()){
asdf qwer = hb.front();
if(qwer.size == 0){
hb.pop();
continue;
}
hb.pop();
while(!hb.empty() && hb.front().x == qwer.x){
qwer.size += hb.front().size;
hb.pop();
}
q.push(qwer);
}
}
return 0;
}
全部评论 1
我直接模拟得 分:
#include <bits/stdc++.h> #define int long long #define endl '\n' using namespace std; void yz(); signed main() { // freopen("Copy!.in", "r", stdin); // freopen("Copy!.out", "w", stdout); ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = 1; // cin >> t; while (t--) yz(); } struct node { int val, id; }; int n; list<node> a; vector<int> ans; bool Find(int x) { int l = 0, r = ans.size() - 1; while (l <= r) { int mid = (l + r) / 2; if (ans[mid] == x) return 1; if (ans[mid] < x) l = mid + 1; else r = mid - 1; } return 0; } void yz() { cin >> n; for (int i = 1; i <= n; ++i) { int x; cin >> x; a.push_back({x, i}); } while (!a.empty()) { ans.clear(); for (auto i = a.begin(); i != a.end(); i++) { i--; auto i1 = i; i++; if (i -> val != i1 -> val || i == a.begin()) ans.push_back(i -> id); } for (auto i = a.begin(); i != a.end(); ) { i--; auto i1 = i; i++; if (Find(i -> id)) i = a.erase(i); else i++; } for (int i : ans) cout << i << " "; cout << "\n"; } }看下面就行了(我的
神奇专属格式)1周前 来自 浙江
0






有帮助,赞一个