P8463 「REOI-1」深潜的第六兽 题解

思路

由于兽是从上往下落的,可以考虑根据 \(h_i\) 的大小从大到小进行排序,遍历到第 \(i\) 座空岛时,查询区间 \(\left[l_i,r_i\right]\) 中兽的数量,之后把区间 \(\left[l_i,r_i\right]\) 清零,然后分别在 \(l_i\)\(r_i\) 上加上区间 \(\left[l_i,r_i\right]\) 中兽的数量即可。可以用线段树或其他你喜欢的数据结构来维护。

由于空岛之间没有重叠部分,所以每次更新操作都不会影响同一高度的空岛,只会影响到下面的空岛。

最终输出兽的总数量即可。

时间复杂度 $ \mathcal O (m\log{R})$,其中 \(R=\max{r_i}\)

代码

#include <bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
using namespace std;

struct node {
	int l, r, h;
} land[500010];
int n, m, w[100010];
int sum[100010 << 2], tag[100010 << 2];
const int mod = 998244353;

bool cmp(node a, node b) {
	return a.h > b.h;
}

void bulid(int x, int l, int r) {
	if (l == r) {
		sum[x] = w[l];
		sum[x] %= mod;
		return;
	}
	int mid = l + r >> 1;
	bulid(ls, l, mid);
	bulid(rs, mid + 1, r);
	sum[x] = sum[ls] + sum[rs];
	sum[x] %= mod;
}

void pushdown(int x) {
	tag[ls] = tag[rs] = tag[x];
	sum[ls] = sum[rs] = 0;
	tag[x] = 0;
}

void update(int x, int L, int R, int l, int r) {
	if (l >= L && r <= R) {
		tag[x] = 1;
		sum[x] = 0;
		return;
	}
	if (tag[x]) {
		pushdown(x);
	}
	int mid = l + r >> 1;
	if (L <= mid) {
		update(ls, L, R, l, mid);
	}
	if (R > mid) {
		update(rs, L, R, mid + 1, r);
	}
	sum[x] = sum[ls] + sum[rs];
	sum[x] %= mod;
}

void add(int x, int st, int l, int r, int data) {
	if (l == r && l == st) {
		sum[x] += data;
		sum[x] %= mod;
		return;
	}
	int mid = l + r >> 1;
	if (tag[x]) {
		pushdown(x);
	}
	if (st <= mid) {
		add(ls, st, l, mid, data);
	}
	if (st > mid) {
		add(rs, st, mid + 1, r, data);
	}
	sum[x] = sum[ls] + sum[rs];
	sum[x] %= mod;
}

int query(int x, int L, int R, int l, int r) {
	if (l >= L && r <= R) {
		return sum[x];
	}
	if (tag[x]) {
		pushdown(x);
	}
	int mid = l + r >> 1, res = 0;
	if (L <= mid) {
		res += query(ls, L, R, l, mid);
	}
	if (R > mid) {
		res += query(rs, L, R, mid + 1, r);
	}
	return res;
}

signed main() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &land[i].l, &land[i].r, &land[i].h);
	}
	for (int i = 1; i <= n; i++) {
		int x;
		scanf("%lld", &x);
		w[x]++;
	}
	sort(land + 1, land + 1 + m, cmp);
	bulid(1, 1, (int)1e5);
	for (int i = 1; i <= m; i++) {
		int l = land[i].l, r = land[i].r;
		int tmp = query(1, l, r, 1, (int)1e5);
		//printf("%d%d%d\n", l, r, tmp);
		update(1, l, r, 1, (int)1e5);
		add(1, l, 1, (int)1e5, tmp);
		add(1, r, 1, (int)1e5, tmp);
	}
	printf("%lld", sum[1]%mod);
	return 0;
}
posted @ 2022-08-15 16:26  Dregen_Yor  阅读(53)  评论(0)    收藏  举报