1.第一步检查数组能否存下 2^26<10^9 存不下
2.只保存有用的信息 有水的水珠 前后可能不连续 用到链表!!
struct node{
int val;
int pre,nex;
}a[40000];
3.如何进行模拟?
4.左右进行模拟 使用链表找前后水珠
5.多个水珠都>=5 怎末办
6.使用优先队列 priority_queue 靠左的先模拟
注意:if (!a[i].w) continue;很重要 否则可能i会被重复添加
核心就是优先队列+链表模拟
7.一直循环直到优先队列为空
超出内存错误答案
#include<bits/stdc++.h>
using namespace std;
int c, m, n;
//检查当前是否有水滴的大于等于5以及对应的位置
vector<int> check(vector<int> grid) {
vector<int> result;
for (int i = 1; i < grid.size(); i++) {
if (grid[i] >= 5)
result.push_back(i);
}
return result;
}
void pprint(vector<int> m) {
for (int i = 1; i < m.size(); i++) {
cout << m[i] << " ";
}
cout << endl;
}
void change(vector<int>& grid) {
vector<int> position;
//pprint(grid);
while (!(position = check(grid)).empty()) {
//最左边的先爆
grid[position[0]] = 0;
//向左寻找
for (int i = position[0]-1; i >= 1; i--) {
if (grid[i] != 0) {
grid[i]++;
break;
}
}
//向右寻找
for (int i = position[0] + 1; i < grid.size(); i++) {
if (grid[i] != 0) {
grid[i]++;
break;
}
}
//pprint(grid);
}
//pprint(grid);
}
int solve(vector<int>& grid, int p) {
grid[p]++;
if (grid[p] >= 5) {
change(grid);
}
//检查有水的格子个数
int num = 0;
for (int i = 0; i < grid.size(); i++) {
if (grid[i] > 0)
num++;
}
return num;
}
int main() {
cin >> c >> m >> n;
vector<int> grid(c + 1, 0);
for (int i = 0; i < m; i++) {
int x, w;
cin >> x >> w;
grid[x] = w;
}
while (n--) {
int p;
cin >> p;
cout<<solve(grid, p)<<endl;
}
return 0;
}
参考别人的正确答案
https://www.cnblogs.com/rabbit1103/p/18213228
#include<bits/stdc++.h>
using namespace std;
/*
1.第一步检查数组能否存下 2^26<10^9 存不下
2.只保存有用的信息 有水的水珠
3.如何进行模拟?
4.左右进行模拟 使用链表找前后水珠
5.多个水珠都>=5 怎末办
6.使用优先队列 靠左的先模拟
7.一直循环直到优先队列为空
*/
int c, m, n, p, cnt;
struct node {
//代表当前是第x格 有w滴水 pre nex代表前驱节点和后继节点
int x, w, pre, nex;
}a[300005];
map<int, int> mp; // 标记i号格子在数组a中的下标
bool cmp(node x, node y) {
return x.x < y.x;
}
priority_queue<int, vector<int>, greater<int>> q;//最小堆 储存a数组下标
int main() {
int i, j, x, w;
scanf("%d%d%d", &c, &m, &n);
for (i = 1; i <= m; i++)
scanf("%d%d", &a[i].x, &a[i].w);
//排序 结点 按照左右顺序
sort(a + 1, a + m + 1, cmp);
// mp[当前结点在真正一维水滴格子的位置]=在a有水滴数组的下标
for (i = 1; i <= m; i++) {
mp[a[i].x] = i;
//前驱节点和后继节点
a[i].pre = i - 1;
a[i].nex = i + 1;
}
cnt = m;//当前有水格子的数量
int pre, nex;
while (n--) {
scanf("%d", &p);
i = mp[p];//在a数组的位置
a[i].w++;
if (a[i].w >= 5)
q.push(i);
while (!q.empty()) {
i = q.top();
q.pop();
//已经在优先队列中的水可能受到后续影响已经爆开了 爆开了就清零
if (!a[i].w) continue;
pre = a[i].pre;
nex = a[i].nex;
//爆开
cnt--;
a[i].w = 0;
//左右遍历
a[pre].w++;
a[nex].w++;
//链表删除
a[pre].nex = nex;
a[nex].pre = pre;
//因为我的链表很大 要确定不是0 或者nex是最后一个元素的下一个 特殊值判断吧
if (pre > 0 && a[pre].w >= 5)
q.push(pre);
if (nex <= m && a[nex].w >= 5)
q.push(nex);
}
printf("%d\n",cnt);
}
return 0;
}