扫描线求条
查看原帖
扫描线求条
831011
Deltary_楼主2025/7/30 16:55
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdint>
#include <cstring>
using namespace std;
#define int int64_t
namespace IO {
	inline int read() {
		int x = 0, f = 1;
		char ch = getchar();
		while (ch > '9' || ch < '0') {
			if (ch == '-') f = -1;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch - 48), ch = getchar();
		return x * f;
	}
	void write(int x) {
		if (x < 0) {
			x = -x;
			putchar('-');
		}
		if (x > 9) write(x / 10);
		putchar(x % 10 + '0');
		return;
	}
}
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int inf = 1e9;
using namespace IO;
#define ls (u << 1)
#define rs (u << 1 | 1)
int n, m, val[N];
struct Msg {
	int len, a, s; 
	Msg() : len(0), a(0), s(0) {}
	Msg(int LEN, int A, int S) : len(LEN), a(A), s(S) {}
	Msg operator + (const Msg &p) const {
		return Msg(len + p.len, a + p.a, s + p.s);
	}
};
struct Tag {
	int dt, k, b;
	Tag() : dt(0), k(0), b(0) {}
	Tag(int Dt, int K, int B) : dt(Dt), k(K), b(B) {}
	// a' = a + dt
	// s' = k * a + b
	// 继承
	bool empty() {
		return !(dt || k || b);
	}
	Tag operator * (const Tag &p) const {
		return Tag(dt + p.dt, k + p.k, b + p.b + k * p.dt);
	}
	// 应用蓝标记
	Msg apply(Msg &p) {
		return Msg(p.len, p.a + dt * p.len, (k * p.a + b) * p.len + p.s);
	}
};
Msg t[N << 2];
Tag lazy[N << 2];
//赋值
void Apply(int u, Tag tag) {
	t[u] = tag.apply(t[u]);
	lazy[u] = tag * lazy[u];
	return void(0);
}
void Pushup(int u) {
	return t[u] = t[ls] + t[rs], void(0);
}
void Pushdown(int u) {
	if(lazy[u].empty()) return void(0);
	Apply(ls, lazy[u]); Apply(rs, lazy[u]);
	lazy[u] = Tag();
	return void(0);
}
void Build(int u, int l, int r) {
	if(l == r) {
		t[u] = Msg(1, 0, 0);
		return void(0);
	}
	int mid = (l + r) >> 1;
	Build(ls, l, mid); Build(rs, mid + 1, r);
	Pushup(u);
	return void(0);
}
void Modify(int u, int l, int r, int L, int R, Tag x) {
	if(L <= l && r <= R) {
		Apply(u, x);
		return void(0);
	}
	int mid = (l + r) >> 1; Pushdown(u);
	if(L <= mid) Modify(ls, l, mid, L, R, x);
	if(R > mid) Modify(rs, mid + 1, r, L ,R, x);
	Pushup(u);
	return void(0);
}
Msg Query(int u, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		return t[u];
	}
	int mid = (l + r) >> 1; Pushdown(u);
	Msg res;
	if(L <= mid) res = res + Query(ls, l, mid, L, R);
	if(R > mid) res = res + Query(rs, mid + 1, r, L, R);
	return res;
}
typedef pair<int, int> pii;
int s[N], top = 0;
int pre[N], suf[N];
vector <pair<pii, int> > Q[N]; // 处理修改
vector <pii> ansp[N], ansm[N];   // 处理询问
int ans[N];
void solve() {
	n = read(), m = read();
	for(int i = 1; i <= n; i++) val[i] = read();
	//单调栈
	for(int i = 1; i <= n; i++) {
		while(top && val[i] < val[s[top]]) top--;
		pre[i] = s[top];
		s[++top] = i;
	}
	top = 0, s[0] = n + 1;
	for(int i = n; i >= 1; i--) {
		while(top && val[i] <= val[s[top]]) top--;
		suf[i] = s[top];
		s[++top] = i;
	}
	//以下
	// 贡献区间 : l in [pre[i] + 1, i], r in [i, suf[i] - 1]
 	for(int i = 1; i <= n; i++) {
		// (l, r) = (pre[i] + 1, i)  from i ~ suf[i] - 1
		Q[suf[i]].push_back({{pre[i] + 1, i}, -val[i]});
		Q[i].push_back({{pre[i] + 1, i}, val[i]});
	}
	Build(1, 1, n);
	//询问 (l, l) -> (r, r) 
	for(int i = 1; i <= m; i++) {
		int l = read(), r = read();
		ansp[r].push_back({l, r});
		ansm[l - 1].push_back({l, r});
	}
	for(int i = 1; i <= n; i++) {
		for(auto k : Q[i]) {
			int l = k.first.first, r = k.first.second, x = k.second;
			Modify(1, 1, n, l, r, Tag(x, 0, 0));
		}
		Modify (1, 1, n, 1, n, Tag(0, 1, 1));
		for(auto [l, r] : ansp[i]) {
			ans[i] += Query(1, 1, n, l, r).s;
		}
		for(auto [l, r] : ansm[i]) {
			ans[i] -= Query(1, 1, n, l, r).s;
		}
	}
	for(int i = 1; i <= m; i++) {
		cout << ans[i] << endl;
	}
	return void(0);
}
int32_t main() {
	int T = 1; while(T--) solve();
	return 0;
}
2025/7/30 16:55
加载中...