P8868 [NOIP2022] 比赛

写来记录一下这种套路。

区间 max 可以单调栈 ++ 扫描线转化成区间加。

询问区间的子区间权值之和,应用到区间历史和上。

此时区间上 Ai=maxj=iraj,Bi=maxj=irbjA_i=\max_{j=i}^{r} a_j, B_i=\max_{j=i}^{r} b_j

询问 Ai×BiA_i\times B_i 的历史和。

扔 [https://www.luogu.com.cn/blog/command-block/guan-yu-xian-duan-shu-shang-di-yi-suo-jin-jie-cao-zuo]。

发现这类历史值问题,考虑标记间的合并即可。

写给自己看的-》结构体内的 add 函数。

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
typedef pair<int, int> pii;
#define F(i, a, b) for(int i = a; i <= (b); ++i)
#define F2(i, a, b) for(int i = a; i < (b); ++i)
#define dF(i, a, b) for(int i = a; i >= (b); --i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug debug("Passing [%s] in LINS %d\n", __FUNCTION__, __LINE__)
#define pb push_back
#define fi first
#define se second
typedef long long ll;
//namespace Fread {const int SIZE = 1 << 17; char buf[SIZE], *S, *T; inline char getchar() {if (S == T) {T = (S = buf) + fread(buf, 1, SIZE, stdin); if (S == T) return '\n';} return *S++;}}
//namespace Fwrite {const int SIZE = 1 << 17; char buf[SIZE], *S = buf, *T = buf + SIZE; inline void flush() {fwrite(buf, 1, S - buf, stdout), S = buf;} inline void putchar(char c) {*S++ = c;if (S == T) flush();} struct NTR {~NTR() {flush();}} ztr;}
//#ifdef ONLINE_JUDGE
//#define getchar Fread::getchar
//#define putchar Fwrite::putchar
//#endif
inline int ri() {
	int x = 0, f = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x * f;
}
inline void wi(int x) {
	if (x < 0) {
		putchar('-'), x = -x;
	}
	if (x > 9) wi(x / 10);
	putchar(x % 10 + 48);
}
inline void wi(int x, char s) {
	wi(x), putchar(s);
}
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3f;
const int _ = 3e5 + 5;
int n, q, a[_], b[_], top, st[_], top2, st2[_], ans[_];
vector<pii> d[_];
struct node {
	int len, u, tgx, tgy, mtgx, mtgy, mtgxy, sx, sy, sxy, msxy;
	void add(int _tgx, int _tgy, int _mtgx, int _mtgy, int _mtgxy, int _u) {
		msxy += _u * sxy + sx * _mtgy + sy * _mtgx + len * _mtgxy;
		mtgxy += _u * tgx * tgy + tgy * _mtgx +  tgx * _mtgy + _mtgxy;
		mtgx += _u * tgx + _mtgx, mtgy += _u * tgy + _mtgy;
		sxy += _tgx * sy + _tgy * sx + len * _tgx * _tgy;
		sx += _tgx * len, sy += _tgy * len;
		tgx += _tgx, tgy += _tgy;
		u += _u;
	}
} tr[_ << 2];
void up(int o) {
	tr[o].sx = tr[o << 1].sx + tr[o << 1 | 1].sx;
	tr[o].sy = tr[o << 1].sy + tr[o << 1 | 1].sy;
	tr[o].sxy = tr[o << 1].sxy + tr[o << 1 | 1].sxy;
}
void build(int o, int l, int r) {
	tr[o].len = r - l + 1;
	if (l == r) return void();
	int mid = (l + r) >> 1;
	build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
	up(o);
}
void pd(int o) {
	if(tr[o].tgx || tr[o].tgy || tr[o].mtgx || tr[o].mtgy || tr[o].mtgxy || tr[o].u) {
		tr[o << 1].add(tr[o].tgx, tr[o].tgy, tr[o].mtgx, tr[o].mtgy, tr[o].mtgxy, tr[o].u);
		tr[o << 1 | 1].add(tr[o].tgx, tr[o].tgy, tr[o].mtgx, tr[o].mtgy, tr[o].mtgxy, tr[o].u);
		tr[o].tgx = tr[o].tgy = tr[o].mtgx = tr[o].mtgy = tr[o].mtgxy = tr[o].u = 0;
	}
}
void add(int o, int l, int r, int L, int R, int c) {
	if (L <= l && r <= R) return tr[o].add(c, 0, 0, 0, 0, 0), void();
	int mid = (l + r) >> 1;
	pd(o);
	if (L <= mid) add(o << 1, l, mid, L, R, c);
	if (R > mid) add(o << 1 | 1, mid + 1, r, L, R, c);
	up(o);
}
void add2(int o, int l, int r, int L, int R, int c) {
	if (L <= l && r <= R) return tr[o].add(0, c, 0, 0, 0, 0), void();
	int mid = (l + r) >> 1;
	pd(o);
	if (L <= mid) add2(o << 1, l, mid, L, R, c);
	if (R > mid) add2(o << 1 | 1, mid + 1, r, L, R, c);
	up(o);
}
//void upd(int o, int l, int r, int L, int R) {
//	if (L <= l && r <= R) return tr[o].add(0, 1), void();
//	int mid = (l + r) >> 1;
//	pd(o);
//	if (L <= mid) upd(o << 1, l, mid, L, R);
//	if (R > mid) upd(o << 1 | 1, mid + 1, r, L, R);
//	up(o);
//}
int qry(int o, int l, int r, int L, int R) {
	if (L <= l && r <= R) return tr[o].msxy;
	int mid = (l + r) >> 1, res = 0;
	pd(o);
	if (L <= mid) res = qry(o << 1, l, mid, L, R);
	if (R > mid) res += qry(o << 1 | 1, mid + 1, r, L, R);
	return res;
}
signed main() {
	int T = ri();
	n = ri();
	F(i, 1, n) a[i] = ri();
	F(i, 1, n) b[i] = ri();
	q = ri();
	F(i, 1, q) {
		int l = ri(), r = ri();
		d[r].pb({l, i});
	}
	build(1, 1, n);
//	cout << tr[1].p << "!!\n";
	F(i, 1, n) {
		while (top && a[st[top]] < a[i]) {
			add(1, 1, n, st[top - 1] + 1, st[top], a[i] -a[st[top]]);
//			cout << "A : " << st[top - 1] + 1 << " " << st[top] << " " << a[i] - a[st[top]] << "\n";
			top--;
		}
		while(top2 && b[st2[top2]] < b[i]) {
			// max -> xi
			add2(1, 1, n, st2[top2 - 1] + 1, st2[top2], b[i] - b[st2[top2]]);
//			cout << "B : " << st2[top2 - 1] + 1 << " " << st2[top2] << " " << b[i] - b[st[top]] << "\n";
			top2--;
		}
		st[++top] = i, st2[++top2] = i;
		add(1, 1, n, i, i, a[i]), add2(1, 1, n, i, i, b[i]);
		tr[1].add(0, 0, 0, 0, 0, 1);
//			cout << "A : " << i << " " << i << " " << a[i] << "\n";
//			cout << "B : " << i << " " << i << " " << b[i] << "\n";
//			cout << tr[1].sxy << ' ' << tr[1].msxy << "!!!\n";
//		cout << "get\n";
		for (pii v : d[i]) {
			ans[v.se] = qry(1, 1, n, v.fi, i);
		}
	}
	F(i, 1, q) wi(ans[i], '\n');
}

/*
  0 2
  2 1
  1 2
  1
  1 2
  
  0 2
  2 1
  1 2
  1
  1 2
 */
posted @ 2023-03-16 17:22  蒟蒻orz  阅读(26)  评论(0)    收藏  举报  来源