【BZOJ 4636】蒟蒻的数列
http://www.lydsy.com/JudgeOnline/problem.php?id=4636
DCrusher贡献的题目
看了他的博客,有两种做法,动态开点线段树和离线操作离散化区间线段树,都是标记永久化,最后统一下放标记算出答案。
动态开点线段树速度更快,但是今天李佳蔚讲了stl的用法,包括用unique和lower_bound离散化,所以这道题就用离散化写了_(:з」∠)_
学习了新的离散化方式(较之前我用id域来离散化,这种二分查找离散化方式常数大一点但代码量少很多)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 400003; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 3) + (k << 1) + c - '0'; return k * fh; } struct node{int l, r, k;} q[N]; int lazy[N << 2], sum[N], n; int L, R, num; void update(int rt, int l, int r) { if (L <= l && r <= R) { lazy[rt] = max(lazy[rt], num); return; } int mid = (l + r) >> 1; if (L <= mid) update(rt << 1, l, mid); if (R > mid) update(rt << 1 | 1, mid + 1, r); } ll Q(int rt, int l, int r) { if (l == r) return 1ll * lazy[rt] * sum[l]; int mid = (l + r) >> 1; lazy[rt << 1] = max(lazy[rt << 1], lazy[rt]); lazy[rt << 1 | 1] = max(lazy[rt << 1 | 1], lazy[rt]); return Q(rt << 1, l, mid) + Q(rt << 1 | 1, mid + 1, r); } int H[N << 1]; int main() { int t = in(), tot = 0; for(int i = 1; i <= t; ++i) { q[i].l = in(); q[i].r = in(); q[i].k = in(); H[++tot] = q[i].l; H[++tot] = q[i].r; } sort(H + 1, H + tot + 1); tot = unique(H + 1, H + tot + 1) - H; n = tot - 2; for(int i = 1; i <= n; ++i) sum[i] = H[i + 1] - H[i]; for(int i = 1; i <= t; ++i) { q[i].l = lower_bound(H + 1, H + tot, q[i].l) - H; q[i].r = lower_bound(H + 1, H + tot, q[i].r) - H; } for(int i = 1; i <= t; ++i) { L = q[i].l; R = q[i].r - 1; num = q[i].k; update(1, 1, n); } printf("%lld\n", Q(1, 1, n)); return 0; }
还有一定注意区间要设为左闭右开!否则找离散后的区间就不太容易了QAQ
NOI 2017 Bless All