首页 > 其他分享 >洛谷 P9912 Zatopljenje

洛谷 P9912 Zatopljenje

时间:2024-09-04 19:47:07浏览次数:14  
标签:洛谷 rs int P9912 Zatopljenje ls

洛谷 P9912 Zatopljenje

题意

给出长度为 \(n\) 的序列 \(a\),有 \(q\) 次询问。

每次给出 \(l,r,x\),询问区间 \([l,r]\) 中有多少段极长的,\(a\) 都大于 \(x\) 的段。

思路

离线后扫描线。

先把询问和 \(a\) 离散化,然后扫描 \(a\) 的值。

维护序列 \(b\),初始全为 \(1\)。

扫描从 \(0\) 到离散化后的最大值,

扫描到一个值 \(v\) 时,对于所有 \(i(a_i=v)\),将 \(b_i \leftarrow 0\)。

同时处理所有 \(x=v\) 的询问,即查询 \(b\) 中区间内有多少段连续的 \(1\)。

单点修改,区间查询,可使用线段树维护。

时间复杂度:\(O(n \log n)\)。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
struct segt {
	struct node {
		int l, r;
		int left, right;
		int cnt;	
	} t[N << 2];
	#define ls (p << 1)
	#define rs (p << 1 | 1) 
	friend node operator + (node a, node b) {
		node res; res.l = a.l, res.r = b.r;
		if (a.cnt && b.cnt) {
			res.left = a.left, res.right = b.right;
			res.cnt = a.cnt + b.cnt;
			if (a.right + 1 == b.left) res.cnt --;
		} else if (a.cnt) {
			res.left = a.left, res.right = a.right;
			res.cnt = a.cnt;	
		} else if (b.cnt) {
			res.left = b.left, res.right = b.right;
			res.cnt = b.cnt;
		} else {
			res.left = -1, res.right = -1;
			res.cnt = 0;
		}
		return res;
	}
	void build(int p, int l, int r, int* a) {
		if (l == r) {
			t[p] = {l, r, l, r, 1};
			return ;
		}
		int mid = (l + r) >> 1;
		build(ls, l, mid, a);
		build(rs, mid + 1, r, a);
		t[p] = t[ls] + t[rs];
	}
	void del(int p, int id) {
		if (t[p].l == t[p].r) {
			t[p] = {t[p].l, t[p].r, -1, -1, 0};
			return ;
		}
		if (id <= t[ls].r) del(ls, id);
		else del(rs, id);
		t[p] = t[ls] + t[rs];
 	}
 	node query(int p, int l, int r) {
		if (l <= t[p].l && t[p].r <= r) return t[p];
		node res; res.l = -1;
		if (t[ls].r >= l) res = query(ls, l, r);
		if (t[rs].l <= r) {
			if (res.l == -1) res = query(rs, l, r);
			else res = res + query(rs, l, r);
		}
		return res;
	}
} T;
struct Query {int l, r, h, id;};
int n, q, a[N], b[N], tot, ans[N];
Query Q[N];
vector <int> M[N], OP[N];
int main() {
	scanf("%d%d", &n, &q);	
	for (int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		b[++ tot] = a[i]; 	
	}
	for (int i = 1; i <= q; i ++) {
		scanf("%d%d%d", &Q[i].l, &Q[i].r, &Q[i].h);
		b[++ tot] = Q[i].h, Q[i].id = i;
	}
	b[++ tot] = 0;
	sort(b + 1, b + tot + 1);
	tot = unique(b + 1, b + tot + 1) - b - 1;
	for (int i = 1; i <= n; i ++) {
		a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
		M[a[i]].push_back(i);
	}
	for (int i = 1; i <= q; i ++) {
		Q[i].h = lower_bound(b + 1, b + tot + 1, Q[i].h) - b;	
		OP[Q[i].h].push_back(i);
	}
	T.build(1, 1, n, a);
	for (int i = 1; i <= tot; i ++) {
		for (auto v : M[i]) T.del(1, v);
		for (auto v : OP[i]) {
			auto op = Q[v];
			auto res = T.query(1, op.l, op.r);
			ans[op.id] = res.cnt;
		}
	}
	for (int i = 1; i <= q; i ++) printf("%d\n", ans[i]);
	return 0;
}

标签:洛谷,rs,int,P9912,Zatopljenje,ls
From: https://www.cnblogs.com/maniubi/p/18397248

相关文章

  • 洛谷 P5340 大中锋的游乐场
    洛谷P5340大中锋的游乐场题意给出一张\(n\)个点\(m\)条边的图,每个点有一个点权\(1\)或\(-1\)。给出点\(s,t\),求出\((s,t)\)间满足以下条件的最短路。任意时刻,走过的路径上点权和均\(\in[-k,k]\)。思路分层图最短路。\(dis_{i,j}\)表示走到\(i\),点权和为\(j......
  • 洛谷 P5618 堵塞的交通
    洛谷P5618堵塞的交通题意有一个\(2\timesC\)的网格图,需要维护\(3\)种操作。连接相邻的两个格子。将相邻的两个格子断开连接。询问两个格子是否联通。思路1考虑分块。连边时块内使用并查集维护,块与块之间用数组标记。删边块内的边时暴力重构并查集,块之间的边清零......
  • 洛谷 B3645 数列前缀和 2 题解
    前缀知识:枚举,费马小定理,逆元,线性乘法逆元,线段树(?)。解法1:暴力如题。暴力枚举即可,30分。由于太简单,不给代码。解法2:前缀积+费马小定理+逆元由于涉及静态区间,可以想到前缀积。前缀积公式为\(q_r/q_{l-1}\),除法恰好可以用逆元来算。直接写即可。不会超时,因为时间为\(O(n\logp)\)......
  • 洛谷题单指南-常见优化技巧-P3143 [USACO16OPEN] Diamond Collector S
    原题链接:https://www.luogu.com.cn/problem/P3143题意解读:找到两个不相交的最长连续序列,使得序列最大值和最小值差不超过k,求两个最长的序列长度和。解题思路:先将所有数从小到大排序,记为a[]要找到两个不相交的最长连续序列,可以采用下面技巧:设b[i]表示i之前“差值在k之内的连续......
  • 洛谷题单指南-常见优化技巧-P4653 [CEOI2017] Sure Bet
    原题链接:https://www.luogu.com.cn/problem/P4653题意解读:选中的灯泡中,某一类较少的总权值减去灯泡数量所得到的收益最大值。解题思路:注意,此题关键是:要使得较少的收益最大化1、要最大化,意味着每次应该选择尽可能大权值的灯泡2、要使A、B类中较少的收益最大化,意味着每次应该优......
  • 洛谷题单指南-常见优化技巧-唯一的雪花 Unique Snowflakes
    原题链接:https://www.luogu.com.cn/problem/UVA11572题意解读:本质上是要计算最长连续不重复子序列的长度,典型的双指针应用。解题思路:通过双指针来枚举子序列,右指针指向的元素每次记录元素出现的次数,可以借助hash数组h[]如果枚举到的元素出现次数超过1,则表示左、右指针之间的子......
  • 洛谷题单指南-常见优化技巧-P2216 [HAOI2007] 理想的正方形
    原题链接:https://www.luogu.com.cn/problem/P2216题意解读:在矩阵中找n*n正方形里最大值和最小值差值的最小值。解题思路:1、枚举法直接枚举所有n*n的正方形的位置,然后在遍历求最大值、最小值,复杂度为O(n^4),显然不能通过。2、二维单调队列既然是求正方形范围内的最值,看起来是......
  • 洛谷题单指南-常见优化技巧-P2032 扫描
    原题链接:https://www.luogu.com.cn/problem/P2032题意解读:求滑动窗口内的最大值,典型的单调队列应用。解题思路:单调队列的三部曲:1、去头。已存入的元素个数超过k,则去头。注意队列里存的是元素下标,只需要用当前下标减去队头元素来判断即可。2、去尾。根据单调队列的单调性,如果......
  • 洛谷 P4819 杀人游戏
    洛谷P4819杀人游戏题意有\(n\)个人,他们之中有一个杀手。每个人都有可能是杀手,并且概率相等。你可以询问若干人。若询问的人是杀手,你会被干掉。若询问的人是平民,你会知道他认识的所有人的身份。给出一张有向图表示这\(n\)个人的关系。求出你活着知道杀手是谁的概率。......
  • 洛谷 P3225 矿场搭建
    洛谷P3225矿场搭建题意煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请......