社区讨论

巨佬求助(码风绝对良好,代码附有注释!!)!!刚学OI,必关必关,非常紧急,谢谢

学术版参与者 6已保存回复 12

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
12 条
当前快照
1 份
快照标识符
@mhj2vxqa
此快照首次捕获于
2025/11/03 19:50
4 个月前
此快照最后确认于
2025/11/03 20:41
4 个月前
查看原帖
求助大佬们,谢谢,如果你已经点进来了,就救救孩子吧,真的很紧急,要死了,有点出去良心真的过得去吗,具体的代码如下
第一题的代码错误为RE+WA:
CPP
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
typedef long long ll;
const int N = 3e5 + 10;
struct Ryan { // 输入时的结构体
    int c, w, p;
}a[N];
struct Frina { // 限制结构体
    int t;
    ll h;
}b[N];

int n, v, m, p[N], sz, c[N]; // p为离散化数组,c[i]表示为颜色为i的石头的个数
ll w[N];
std::vector <Ryan> k[N]; // 每一个坑里的宝石的数据
bool vis[N], flag[N]; // flag[i]表示点i有没有被选过,vis[i]表示为颜色为i的石头是否已经满足条件
int get_id(int val) {return std::lower_bound(p + 1, p + sz + 1, val) - p;} // 二分求离散化

int main() {
    scanf("%d%d%d", &n, &m, &v);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &a[i].c, &a[i].w, &a[i].p), p[i] = a[i].p;

    std::sort(p + 1, p + n + 1); // 对坑进行离散化
    sz = std::unique(p + 1, p + n + 1) - p - 1;
    for (int i = 1; i <= n; i++) {
        int idx = get_id(a[i].p);
        k[idx].push_back(a[i]);
    }

    // for (int i = 1; i <= sz; i++)
    //     printf("%d%c", p[i], i == sz ? '\n' : ' ');

    int l = 1, cnt = 0; // l 为走指针的左端点,cnt表示为有多少种宝石已经满足要求
    ll ans = 0; // ans 记为答案
    for (int i = 1; i <= m; i++) {
        scanf("%d%lld", &b[i].t, &b[i].h);
        if (b[i].t == 0 && b[i].h == 0) { // 特判一下,如果直接满足要求就直接增加
            vis[i] = true;
            cnt ++;
        }
    }
    
    memset(flag, 1, sizeof flag);
    flag[0] = 0; p[0] = 0;
    for (int i = 1; i <= sz; i++) {
        for (Ryan val : k[i]) {
            w[val.c] += val.w; // 更新每种石头的大小与数量
            c[val.c] ++;

            if (!vis[val.c] && w[val.c] >= b[val.c].h && c[val.c] >= b[val.c].t) { // 判断满足要求的石头的个数
                vis[val.c] = true;
                cnt ++;
            }
        }
        // for (int j = 1; j <= m; j++)
        //     printf("%d %d %d\n", c[j], w[j], vis[j]);
        // printf("%d\n\n", cnt);

        // printf("%d\n", cnt);
        while (cnt == m) { // 既然满足条件,那么开始记答案
            ans += 1LL * (v - p[i] + 1) * (p[l] - p[l - 1] + flag[l - 1]); // 因为l~i的区间满足,所以扩大i的区间照样满足,更新答案
            flag[l] = 0; // 标记这个端点已经被算过了

            for (Ryan val : k[l]) {
                w[val.c] -= val.w; // "回溯"
                c[val.c] --;
                if (vis[val.c] && (w[val.c] < b[val.c].h || c[val.c] < b[val.c].t)) {
                    vis[val.c] = false;
                    cnt --;
                }
            }

            l ++; // 左端点变化
        }
    }

    printf("%lld\n", ans);
    return 0;
}
第二题代码错误为WA:
CPP
#include <cstdio>
#include <algorithm>
#include <queue>
#define int long long
typedef long long ll;
const int N = 1e6 + 10;

struct Ryan { // 堆
    int pos;
    ll cnt;

    bool operator<(const Ryan &a) const { // 重载运算符
        if (cnt != a.cnt) return cnt < a.cnt; // 先按照个数从大到小排列 (个数)
        return pos > a.pos; // 在按照从小到大排列(数值)
    }
};
struct Frina {
    int val;
    ll w;
}q[N];
int id, n, val[N], sz;
ll cnt[N]; // 个数
std::priority_queue <Ryan> pq; // 堆

int get_id(int k) { // 离散化求下标,用二分
    int l = 1, r = sz, res = 0;

    while (l <= r) {
        int mid = l + r >> 1;

        if (val[mid] <= k) {
            res = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }

    return res;
}

signed main() {
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &q[i].val, &q[i].w), val[i] = q[i].val; // 读入

    std::sort(val + 1, val + n + 1);
    sz = std::unique(val + 1, val + n + 1) - val - 1; // 离散化

    for (int i = 1; i <= sz; i++) // 初值
        pq.push({i, 0}); // 一维表示下标,二维表示个数

    int ans = 0; // ans为众数所对应的数
    ll maxn = 0; // 众数的个数
    for (int i = 1; i <= n; i++) {
        int idx = get_id(q[i].val); // 离散化先求下标

        if (q[i].w > 0) { // 如果是增加
            cnt[idx] += q[i].w;

            if (maxn == cnt[idx] && val[idx] < ans) ans = val[idx]; // 加后相等,取较小值
            if (maxn < cnt[idx]) { // 加后变大,更新最大值
                maxn = cnt[idx];
                ans = val[idx];
            }
        }
        else {
            if (cnt[idx] != maxn) cnt[idx] += q[i].w; // 初始不等于,就不影响答案
            else { // 否则在堆里寻找答案
                cnt[idx] += q[i].w;
                while (true) {
                    Ryan t = pq.top(); pq.pop(); // 此时的t在堆里是出现个数最多的且对于出现个数相等的情况,数值最小的
                    if (cnt[t.pos] != t.cnt) // 如果出现个数不统一,则重新改正
                        pq.push({t.pos, cnt[t.pos]});
                    else { // 否则即是答案
                        if (t.cnt == 0) break; // 如果众数的个数为0,则总集和为空,不更改答案(题目要求)

                        maxn = t.cnt; // 否则改变出现次数
                        ans = val[t.pos]; // 更新数值
                        pq.push(t); // 重新放回堆里
                        break; // 找到答案,跳出
                    }
                }
            }
        }

        printf("%lld\n", ans); // 输出数值
    }
    return 0;
}

回复

12 条回复,欢迎继续交流。

正在加载回复...