题解

wanghaocheng 2024-01-07 16:45:31 2024-01-14 11:06:01 6 返回题目

Solution

暴力

枚举 ,对每个 做一次单调栈即可

正解

从暴力观察到对于每个 ,若对于 它是”成功点“,那么显然对于 它都是”成功点“ (证明考虑前面的点以及点 只需要少消去几个点)。因此考虑离线,对所有 query 按左端点排序,用一个 vector 存 当前 有几个点刚好是“成功点”,并插入 BIT 即可。

The code

赛时比较匆忙,码风不一定很好。简单题懒得封装了。

#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#define INF (0x3f3f3f3f)

using namespace std;

const int MAXN = 500005;

int n, q;
int a[MAXN], b[MAXN];
struct Que {
	int l, r, id;
	inline bool operator < (const Que &y) const {
		return l < y.l;
	}
}qr[MAXN];
int ans[MAXN];

int top, stc[MAXN];
vector<int>vec[MAXN];
inline void Solve() {
	stc[top = 1] = 0;
	for (int i = 1; i <= n; ++ i) {
		while (top && (a[i] == a[stc[top]] || b[i] >= b[stc[top]]))
			-- top;
		vec[stc[top]].push_back(i); 
		stc[++ top] = i;
	}
}

int tr[MAXN];
inline int lowbit(int x) {
	return (x & (-x));
}
inline void add(int p, int x) {
	while (p <= n) tr[p] += x, p += lowbit(p);
}
inline int query(int p) {
	int res = 0;
	while (p) res += tr[p], p -= lowbit(p);
	return res;
}

inline void Calc() {
	int ps = 0;
	for (int i = 1; i <= q; ++ i) {
		while (ps < qr[i].l) {
			for (int u : vec[ps])
				add(u, 1);
			++ ps;
		}
		ans[qr[i].id] = query(qr[i].r) - query(qr[i].l - 1);
	}
}

int main()
{
	scanf ("%d%d", &n, &q);
	for (int i = 1; i <= n; ++ i) scanf ("%d", a + i);
	for (int i = 1; i <= n; ++ i) scanf ("%d", b + i);
	b[0] = INF;
	Solve();
	for (int i = 1; i <= q; ++ i) {
		scanf ("%d%d", &qr[i].l, &qr[i].r);
		qr[i].id = i;
	}
	sort(qr + 1, qr + q + 1);
	Calc();
	for (int i = 1; i <= q; ++ i) printf ("%d\n", ans[i]);
	return 0;
}
{{ vote && vote.total.up }}