社区讨论
巨佬求助(码风绝对良好,代码附有注释!!)!!刚学OI,必关必关,非常紧急,谢谢
学术版参与者 6已保存回复 12
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 12 条
- 当前快照
- 1 份
- 快照标识符
- @mhj2vxqa
- 此快照首次捕获于
- 2025/11/03 19:50 4 个月前
- 此快照最后确认于
- 2025/11/03 20:41 4 个月前
求助大佬们,谢谢,如果你已经点进来了,就救救孩子吧,真的很紧急,要死了,有点出去良心真的过得去吗,具体的代码如下
第一题的代码错误为RE+WA:
CPP第一题的代码错误为RE+WA:
#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 条回复,欢迎继续交流。
正在加载回复...