十滴水 第33次CCF-CSP计算机软件能力认证

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值