当前位置: 首页 > news >正文

P14152 千手百眼,天下人间

题目传送门

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;
}
http://www.jsqmd.com/news/70086/

相关文章:

  • 2025 年 12 月不锈钢无缝管实力厂家权威推荐榜:医疗/流体/异形/薄壁/半导体/精密无缝管,匠心工艺与卓越性能深度解析 - 品牌企业推荐师(官方)
  • 网线网络连接上,但是无法上网,报这个错dns_probe_finished_bad_config解决方法
  • 2025广州比较好的留学中介机构港硕申请 - 留学机构评审官
  • 2025广州出国留学中介 - 留学机构评审官
  • 2025年阜阳人行通道闸企业综合推荐榜单 - 2025年11月品牌推荐榜
  • 2025北京十大留学中介有哪些公司 - 留学机构评审官
  • 2025北京十大留学中介有哪些公司 - 留学机构评审官
  • 【ICPS出版 | EI检索】第三届人工智能、系统与网络安全国际学术会议 (AISNS 2025)
  • 2025年质量好的取向电工钢实力与信誉双榜(权威推荐) - 行业平台推荐
  • 2025北京知名留学中介机构排名前十 - 留学机构评审官
  • 2025北京最大的留学中介机构 - 留学机构评审官
  • 2025北京最牛的留学中介 - 留学机构评审官
  • 河北省邢台市任泽区农村自建房找谁好?河北省邢台市任泽区自建房公司/机构深度评测口碑推荐榜 - 苏木2025
  • 2025年国内做得好的高效粉碎机制造企业哪个好,JFG-C系列高效沸腾干燥机/JGF-B系列高效粉碎机订做厂家选哪家 - 品牌推荐师
  • 2025留学机构十强北京 - 留学机构评审官
  • 赤城县自建房找谁好?河北张家口赤城县自建房公司/机构深度评测口碑推荐 - 苏木2025
  • 2026年河北张家口市赤城县农村自建房推荐榜,图南建房宝领衔 六家实力公司赋能乡村宜居生活 - 苏木2025
  • 在河北省邢台市信都区老家农村盖房子,靠谱的自建房公司口碑推荐。河北省邢台市信都区自建房公司/机构权威测评推荐排行榜 - 苏木2025
  • 2025年果壳活性炭厂家综合推荐:十大优质供应商盘点 - 2025年11月品牌推荐榜
  • JS 原生数组(Array)的迭代器 不是 基于生成器(Generator)实现的 - jerry
  • 2025年打包机生产厂商交货速度哪家快、打包机生产商性价比排 - myqiye
  • VIP
  • 河北省邢台市信都区农村自建房找谁好?河北省邢台市信都区自建房公司/机构深度评测口碑推荐榜 - 苏木2025
  • 2025年十大泡沫保温板实力供应商推荐:服务不错的泡沫保温板 - 工业推荐榜
  • 【代码开源】基于 STM32 的智能空气加湿器设计与实现
  • 2025年泡沫保温板实力厂商TOP5推荐,专业泡沫保温板生产 - 工业品牌热点
  • 【合集】【SPIE出版 | EI检索】第二届遥感技术与图像处理国际学术会议(RSTIP 2025)【ICPS出版 | EI检索】第三届人工智能、系统与网络安全国际学术会议 (AISNS 2025)
  • 2025年靠谱的条纹石砖机厂家最新推荐排行榜 - 行业平台推荐
  • 2025年12月东莞封箱胶带厂家推荐排行榜:透明/米黄/彩色/印刷/Logo定制封箱胶,喷漆美纹胶/高粘美纹胶/3M美纹胶,源头工厂实力甄选 - 品牌企业推荐师(官方)
  • ADS1248/1247(TI) 24位ADC详细配置说明