1 条题解
-
0
自动搬运
来自洛谷,原作者为

liheyang123
「假装不在意,直到真的不在意」搬运于
2025-08-24 22:39:44,当前版本为作者最后更新于2025-08-19 21:45:04,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
solution
先考虑特殊的,假设每一组询问 ,满足 那么问题简化为依次执行操作序列的第 项所对应的操作,此时答案为 。
但是对于询问 ,不能直接用 与 对应的答案相见,因为可能会覆盖之前的操作,此处应该可以想到 ODT,离线,将询问挂在 r 上扫描线,对于一段,其操作序列中的顺序是第 个,权值为 ,区间长度为 ,对于 如果被覆盖,其对后续的贡献为 ,记 的对当前贡献为 ,那么显然答案是 。
时间复杂度分析
ODT ,询问总共需要 , 同阶,此处不区分。
code
感觉代码整体很板。 ::::info[使用了AI工具提升代码可读性]
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define int ll namespace FastIO { const int BUFFER_SIZE = 1 << 20; char inbuf[BUFFER_SIZE], outbuf[BUFFER_SIZE]; char *pin = inbuf, *pin_end = inbuf; int outpos = 0; inline char getchar() { if (pin == pin_end) { pin = inbuf; pin_end = inbuf + fread(inbuf, 1, BUFFER_SIZE, stdin); if (pin == pin_end) return EOF; } return *pin++; } template <typename T> inline T read() { T x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch - '0'); ch = getchar(); } return x * f; } template <typename T> inline void write(T x, char end_char = '\n') { if (outpos >= BUFFER_SIZE - 32) { fwrite(outbuf, 1, outpos, stdout); outpos = 0; } if (x < 0) { outbuf[outpos++] = '-'; x = -x; } char temp[64]; int len = 0; do { temp[len++] = x % 10 + '0'; x /= 10; } while (x); while (len--) { outbuf[outpos++] = temp[len]; } outbuf[outpos++] = end_char; } inline void flush() { if (outpos) { fwrite(outbuf, 1, outpos, stdout); outpos = 0; } } } using namespace FastIO; const int MAX_N = 5e5 + 10; // 线段信息结构体 struct Segment { int left, right; // 线段左右端点 int timestamp; // 时间戳(赋值时间) int value; // 线段的值 Segment() : left(0), right(0), timestamp(0), value(0) {} Segment(int l, int r, int t, int v) : left(l), right(r), timestamp(t), value(v) {} // 按左端点排序 bool operator < (const Segment &other) const { if (left != other.left) return left < other.left; if (right != other.right) return right < other.right; if (timestamp != other.timestamp) return timestamp < other.timestamp; return value < other.value; } }; // 查询结构体 struct QueryInfo { int left_bound; // 查询左边界 int query_id; // 查询ID QueryInfo(int l, int id) : left_bound(l), query_id(id) {} }; int n, m, q; int segment_left[MAX_N], segment_right[MAX_N], segment_value[MAX_N]; int answer[MAX_N]; vector<QueryInfo> queries_by_right[MAX_N]; // 珂朵莉树(ODT) set<Segment> odt_set; // 树状数组(用于区间查询) int fenwick_tree[MAX_N]; // 树状数组:单点更新 void update_fenwick(int position, int delta) { for (; position > 0; position -= position & -position) { fenwick_tree[position] += delta; } } // 树状数组:前缀和查询 int query_fenwick(int position) { int result = 0; for (; position <= n; position += position & -position) { result += fenwick_tree[position]; } return result; } // ODT核心操作:在指定位置分割线段 set<Segment>::iterator split_odt(int split_position) { auto iter = odt_set.lower_bound(Segment(split_position, 0, 0, 0)); if (iter != odt_set.end() && iter->left == split_position) { return iter; } iter--; Segment original_segment = *iter; odt_set.erase(iter); // 分割为两个线段 odt_set.insert(Segment(original_segment.left, split_position - 1, original_segment.timestamp, original_segment.value)); auto result = odt_set.insert(Segment(split_position, original_segment.right, original_segment.timestamp, original_segment.value)); return result.first; } // ODT核心操作:区间赋值 void assign_odt(int assign_left, int assign_right, int timestamp, int value) { // 分割出操作区间 auto right_iter = split_odt(assign_right + 1); auto left_iter = split_odt(assign_left); // 删除原有线段的影响 for (auto iter = left_iter; iter != right_iter; ++iter) { const Segment &seg = *iter; int segment_length = seg.right - seg.left + 1; update_fenwick(seg.timestamp, -segment_length * seg.value); } // 删除旧线段,插入新线段 odt_set.erase(left_iter, right_iter); int new_length = assign_right - assign_left + 1; update_fenwick(timestamp, new_length * value); odt_set.insert(Segment(assign_left, assign_right, timestamp, value)); } signed main() { // 读取输入 n = read<int>(), m = read<int>(), q = read<int>(); for (int i = 1; i <= n; i++) { segment_left[i] = read<int>(); segment_right[i] = read<int>(); segment_value[i] = read<int>(); } // 存储查询 for (int i = 1; i <= q; i++) { int query_left = read<int>(), query_right = read<int>(); queries_by_right[query_right].emplace_back(query_left, i); } // 初始化ODT:整个区间初始值为0,时间戳为1 odt_set.insert(Segment(1, m, 1, 0)); // 处理每个时间点的操作 for (int current_time = 1; current_time <= n; current_time++) { // 执行区间赋值操作 assign_odt(segment_left[current_time], segment_right[current_time], current_time, segment_value[current_time]); // 处理当前时间点的所有查询 for (const auto &query_info : queries_by_right[current_time]) { int prefix_sum = query_fenwick(query_info.left_bound); answer[query_info.query_id] = prefix_sum; } } // 输出所有查询结果 for (int i = 1; i <= q; i++) { write(answer[i]); } flush(); return 0; }::::
- 1
信息
- ID
- 8030
- 时间
- 2500ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者