1 条题解
-
0
可以用线段树和差分。设所有高度差分后的数组为 。
对于区间加操作,给 加上 , 减去 即可。区间减同理。
对山丘操作,设 ,对 到 进行区间加 ,对 或 (视区间长度奇偶性而定)到 进行区间减 。峡谷操作同理。
最后第 点的高度就是 到 的和。
//copper_ingot #include <bits/stdc++.h> using namespace std; #define int long long int n, k, tr[800100], lz[800100]; void pushdown(int u, int l, int mid, int r){ tr[u << 1] += lz[u] * (mid - l + 1), tr[u << 1 | 1] += lz[u] * (r - mid); lz[u << 1] += lz[u], lz[u << 1 | 1] += lz[u]; lz[u] = 0; } void modify(int u, int l, int r, int ql, int qr, int v){ if (ql <= l && r <= qr){tr[u] += v * (r - l + 1), lz[u] += v; return;} int mid = (l + r) >> 1; if (lz[u] && l != r) pushdown(u, l, mid, r); if (ql <= mid) modify(u << 1, l, mid, ql, qr, v); if (qr > mid) modify(u << 1 | 1, mid + 1, r, ql, qr, v); tr[u] = tr[u << 1] + tr[u << 1 | 1]; } int query(int u, int l, int r, int ql, int qr){ if (ql <= l && r <= qr) return tr[u]; int mid = (l + r) >> 1, ans = 0; if (lz[u]) pushdown(u, l, mid, r); if (ql <= mid) ans += query(u << 1, l, mid, ql, qr); if (qr > mid) ans += query(u << 1 | 1, mid + 1, r, ql, qr); tr[u] = tr[u << 1] + tr[u << 1 | 1]; return ans; } signed main(){ scanf("%lld%lld", &n, &k); n++; for (int i = 1; i <= k; i++){ char c; int l, r; cin >> c; scanf("%lld%lld", &l, &r); if (c == 'R') modify(1, 1, n, l, l, 1), modify(1, 1, n, r + 1, r + 1, -1); if (c == 'D') modify(1, 1, n, l, l, -1), modify(1, 1, n, r + 1, r + 1, 1); if (c == 'H'){ int mid = (l + r) >> 1; if ((r - l) % 2) modify(1, 1, n, l, mid, 1), modify(1, 1, n, mid + 2, r + 1, -1); else modify(1, 1, n, l, mid, 1), modify(1, 1, n, mid + 1, r + 1, -1); } if (c == 'V'){ int mid = (l + r) >> 1; if ((r - l) % 2) modify(1, 1, n, l, mid, -1), modify(1, 1, n, mid + 2, r + 1, 1); else modify(1, 1, n, l, mid, -1), modify(1, 1, n, mid + 1, r + 1, 1); } } for (int i = 1; i <= n - 1; i++) printf("%lld\n", query(1, 1, n, 1, i)); return 0; }
- 1
信息
- ID
- 8526
- 时间
- 4000ms
- 内存
- 2048MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者