尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

P14152 千手百眼,天下人间

P14152 千手百眼,天下人间
📅 发布时间:2026/6/24 22:58:46

题目传送门

0x00

习题课上怒敲1.5h然后没过
感谢好心的DS大佬Elysia11帮忙改了1h代码!!

0x01

前两个操作都是很简单,难点在于第三个撤销操作
正着操作很难,因为可能后面一个撤销前面所有操作直接无效,所以考虑倒序,优先处理操作3,(很常见的一个思路:正难则反)
考虑维护一棵线段树,再开一个判断操作是否无效的数组,如果有操作3,则将操作3的区间\([l_i,r_i]\)全部打上标记1,在进行操作1、2时判断一下标记是否为1,如果是就直接不操作了。
在维护线段树时可以直接动态开点,复杂度\(O(mlogv)\),也可以用离散化优雅一下,复杂度\(O(mlogm)\)
然后就是正常的线段树了,复杂度\(O(nlogn)\)

0x02 Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
//using ll = long long;
const int MAXN = 5e5 + 10;
const ll INF = 1e18;
long long lowbit(long long x){return x&-x;
}
struct Op {int op, id;ll t;int l, r;ll k;bool operator<(const Op& a)const{if(t!=a.t){return t<a.t;}else if(t==a.t){return id<a.id;}}
};
struct SegNode {ll v, lz;
};
int n, m;
ll a[MAXN];
Op ops[MAXN];
ll ans[MAXN];
int cnt = 0;
int length = 0;
SegNode seg[MAXN * 4];
void build(int node, int l, int r) {seg[node].lz = 0;if (l == r) {seg[node].v = a[l];return;}int mid = (l + r) / 2;build(node * 2, l, mid);build(node * 2 + 1, mid + 1, r);seg[node].v = max(seg[node * 2].v, seg[node * 2 + 1].v);
}
void pd(int node) {if (seg[node].lz != 0) {seg[node * 2].v += seg[node].lz;seg[node * 2].lz += seg[node].lz;seg[node * 2 + 1].v += seg[node].lz;seg[node * 2 + 1].lz += seg[node].lz;seg[node].lz = 0;}
}
void upd(int node, int l, int r, int ql, int qr, ll k) {if (ql <= l && r <= qr) {seg[node].v += k;seg[node].lz += k;return;}pd(node);int mid = (l + r) / 2;if (ql <= mid) {upd(node * 2, l, mid, ql, qr, k);}if (qr > mid) {upd(node * 2 + 1, mid + 1, r, ql, qr, k);}seg[node].v = max(seg[node * 2].v, seg[node * 2 + 1].v);
}
ll qry(int node, int l, int r, int ql, int qr) {if (ql <= l && r <= qr) {return seg[node].v;}pd(node);int mid = (l + r) / 2;ll res = -INF;if (ql <= mid) {res = max(res, qry(node * 2, l, mid, ql, qr));}if (qr > mid) {res = max(res, qry(node * 2 + 1, mid + 1, r, ql, qr));}return res;
}
long long ts[11451411];
int sz;
int get(ll t) {return lower_bound(ts+1, ts+sz+1, t) - ts;
}
int diff[11451411];
void add1(long long x,long long v){while(x<=length){diff[x]+=v;x+=lowbit(x);}
}
void add2(long long l,long long r,long long v){add1(l,v);add1(r+1,-v);
}
long long getsum(long long x){long long ans=0;while(x){ans+=diff[x];x-=lowbit(x);}return ans;
}
int main() {cin >> n >> m;for (int i = 1; i <= n; ++i) {cin >> a[i];}for (int i = 1; i <= m; ++i) {cin >> ops[i].op;if (ops[i].op == 1) {cin >> ops[i].t >> ops[i].l >> ops[i].r >> ops[i].k;} else if(ops[i].op == 2){cin >> ops[i].t >> ops[i].l >> ops[i].r;ops[i].k = 0;} else if(ops[i].op == 3){cin >> ops[i].t >> ops[i].l >> ops[i].r;ops[i].k = 0;ts[++length]=ops[i].l;ts[++length]=ops[i].r;}ops[i].id = i;ts[++length]=ops[i].t;}sort(ops+1,ops+m+1);sort(ts+1,ts+length+1);sz = unique(ts+1,ts+length+1)-ts-1;for (int i = m ; i >= 0; --i) {if (!getsum(get(ops[i].t))&&ops[i].op == 3) {ll L_time = ops[i].l;ll R_time = ops[i].r;int l = get(L_time);int r = get(R_time);add2(l,r,1);}}ll sum = 0;build(1, 1, n);for (int i = 1; i <= m; ++i) {int tid = get(ops[i].t);if (!getsum(get(ops[i].t)) && ops[i].op == 1) {upd(1, 1, n, ops[i].l, ops[i].r, ops[i].k);} else if(!getsum(get(ops[i].t)) && ops[i].op == 2) {ans[cnt++] = qry(1, 1, n, ops[i].l, ops[i].r);}}cout << cnt << "\n";for (int i = 0; i < cnt; ++i) {cout << ans[i] << "\n";}return 0;
}

最后看一眼我的抽象\(70pts\)代码(再次膜拜DS大佬Elysia11!!)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 5e5 + 10;
const ll INF = 1e18;
struct Op {int op, id;ll t;int l, r;ll k;
};
struct SegNode {ll v, lz;
};
int n, m;
ll a[MAXN];
Op ops[MAXN];
ll ans[MAXN];
int cnt = 0;
SegNode seg[MAXN * 4];
void build(int node, int l, int r) {seg[node].lz = 0;if (l == r) {seg[node].v = a[l];return;}int mid = (l + r) / 2;build(node * 2, l, mid);build(node * 2 + 1, mid + 1, r);seg[node].v = max(seg[node * 2].v, seg[node * 2 + 1].v);
}
void pd(int node) {if (seg[node].lz != 0) {seg[node * 2].v += seg[node].lz;seg[node * 2].lz += seg[node].lz;seg[node * 2 + 1].v += seg[node].lz;seg[node * 2 + 1].lz += seg[node].lz;seg[node].lz = 0;}
}
void upd(int node, int l, int r, int ql, int qr, ll k) {if (ql <= l && r <= qr) {seg[node].v += k;seg[node].lz += k;return;}pd(node);int mid = (l + r) / 2;if (ql <= mid) {upd(node * 2, l, mid, ql, qr, k);}if (qr > mid) {upd(node * 2 + 1, mid + 1, r, ql, qr, k);}seg[node].v = max(seg[node * 2].v, seg[node * 2 + 1].v);
}
ll qry(int node, int l, int r, int ql, int qr) {if (ql <= l && r <= qr) {return seg[node].v;}pd(node);int mid = (l + r) / 2;ll res = -INF;if (ql <= mid) {res = max(res, qry(node * 2, l, mid, ql, qr));}if (qr > mid) {res = max(res, qry(node * 2 + 1, mid + 1, r, ql, qr));}return res;
}
int get(const vector<ll>& ts, ll t) {return lower_bound(ts.begin(), ts.end(), t) - ts.begin();
}
int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cin >> n >> m;for (int i = 1; i <= n; ++i) {cin >> a[i];}vector<ll> ts;for (int i = 0; i < m; ++i) {cin >> ops[i].op;if (ops[i].op == 1) {cin >> ops[i].t >> ops[i].l >> ops[i].r >> ops[i].k;} else {cin >> ops[i].t >> ops[i].l >> ops[i].r;ops[i].k = 0;}ops[i].id = i;ts.push_back(ops[i].t);}sort(ts.begin(), ts.end());ts.erase(unique(ts.begin(), ts.end()), ts.end());int sz = ts.size();vector<ll> diff(sz + 2, 0);for (int i = m - 1; i >= 0; --i) {if (ops[i].op == 3) {ll L_time = ops[i].l;ll R_time = ops[i].r;int l = get(ts, L_time);int r = upper_bound(ts.begin(), ts.end(), R_time) - ts.begin() - 1;if (l <= r) {diff[l]++;diff[r + 1]--;}}}vector<bool> valid(sz, true);ll sum = 0;for (int i = 0; i < sz; ++i) {sum += diff[i];if (sum > 0) {valid[i] = false;}}build(1, 1, n);vector<pair<ll, int>> ops2;for (int i = 0; i < m; ++i) {int tid = get(ts, ops[i].t);if (valid[tid] && ops[i].op != 3) {ops2.emplace_back(ops[i].t, ops[i].id);}}sort(ops2.begin(), ops2.end(), [&](const pair<ll, int>& a, const pair<ll, int>& b) {if (a.first != b.first) {return a.first < b.first;}return a.second < b.second;});for (auto& p : ops2) {int i = p.second;if (ops[i].op == 1) {upd(1, 1, n, ops[i].l, ops[i].r, ops[i].k);} else if (ops[i].op == 2) {ans[cnt++] = qry(1, 1, n, ops[i].l, ops[i].r);}}cout << cnt << "\n";for (int i = 0; i < cnt; ++i) {cout << ans[i] << "\n";}return 0;
}
"——敬不完美的明天" "——敬不再沉默的历史,热烈而勇敢的奔赴,和通往所以未来的旅途" "——敬盛会的邀请函,所有的谎言,和唯一的真相" "——敬坚忍的岁月,每个悲伤的夜晚,和终将到来的黎明" "——敬我的过去,现在,未来...和年少时至死不渝的梦" 时钟的指针转过一圈又一圈,但每一天的开始和结束,永远落在「前进」的十二点

相关新闻

  • 网线网络连接上,但是无法上网,报这个错dns_probe_finished_bad_config解决方法
  • 2025 年 12 月不锈钢无缝管实力厂家权威推荐榜:医疗/流体/异形/薄壁/半导体/精密无缝管,匠心工艺与卓越性能深度解析 - 品牌企业推荐师(官方)
  • 2025广州出国留学中介 - 留学机构评审官

最新新闻

  • OpenAI内容审核API高级应用:从原理到生产级策略实战
  • Windows本地AI工作流重构:ZeroClaw实现QQ远程指挥Claude离线运行
  • 告别原生弹窗:构建现代化Web确认对话框的完整指南
  • 深入解析片上仲裁与交换系统:寄存器配置与性能调试实战
  • MATLAB Cody Contest编程竞赛:算法优化与向量化实战指南
  • Claude Skills本质解析:结构化角色约束与垂直领域有限状态机

日新闻

  • 终极指南:如何用shadPS4在电脑上免费畅玩PS4游戏
  • 打造个性化Instagram Clone:主题定制与用户体验优化技巧
  • 未来展望:RoseTTAFold-All-Atom的发展路线图与社区支持资源汇总

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号