【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
", Q(1, 1, n));
	
	return 0;
}

还有一定注意区间要设为左闭右开!否则找离散后的区间就不太容易了QAQ

原文地址:https://www.cnblogs.com/abclzr/p/5668040.html