NOIP2022 比赛

Day \(2^2+3^2+4^2\)

HNOI2016 序列的加强版。我去年怎么这么菜啊,虽然现在也是就是了。

\[\sum\limits_{[l,r]\in [L,R]}\left(\max\limits_{i\in [l,r]}a_i\right)\left(\max\limits_{i\in [l,r]}b_i\right) \]

考虑离线,对右端点 \(r\) 扫描线,对每个左端点 \(l\) 维护 \(S_l=\left(\max\limits_{i\in [l,r]}a_i\right)\left(\max\limits_{i\in [l,r]}b_i\right)\)。然后查询就变成了求历史版本和,由于需要维护最大值,建立关于 \(a_i,b_i\) 的单调栈,题目就变成了:

  1. \(a_i\gets a_i+c,i\in [l,r]\)
  2. \(b_i\gets b_i+c,i\in [l,r]\)
  3. \(c_i\gets c_i+a_ib_i,i\in [l,r]\)
  4. 查询 \(\sum \limits_{i\in [l,r]}c_i\) 的值。

类似上面那题,没有历史版本和的问题时容易的。维护 \(a_i,b_i\) 的区间和、区间加法标记以及 \(a_ib_i\) 的区间和就行了。由于要维护历史版本和,再维护 \(a_i,b_i\) 的区间历史版本和、区间历史加法标记和以及 \(a_ib_i\) 的历史版本和、\(a_i,b_i\) 标记乘积的历史版本和即可。

// Problem: #3899. 「NOIP2022」比赛
// Contest: LibreOJ
// URL: https://loj.ac/p/3899
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define mt make_tuple
#define mp make_pair
#define fi first
#define se second
// #define FILE

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int> tu;
bool Mbe;

const int N = 3e5 + 300;

int n, m, a[N], b[N], tp[2], st[N][2];
ull ans[N];
vector<pi> q[N];

struct node {
	ull sa, sb, sab, ta, tb, len;
	ull hsa, hsb, hsab, hta, htb, htab, ti;
	node () { sa = sb = sab = ta = tb = len = hsa = hsb = hsab = hta = htb = htab = ti = 0; }
} tr[N << 2];

node tag (ull _ta, ull _tb, ull _ti) { node res; res.ta = _ta, res.tb = _tb, res.ti = _ti; return res; }
#define ls x << 1
#define rs x << 1 | 1
#define mid ((l + r) >> 1)

void ptg(node &x, node y) {
	x.hsab += x.sab * y.ti + x.sb * y.hta + x.sa * y.htb + x.len * y.htab;
	x.hsa += x.sa * y.ti + x.len * y.hta, x.hsb += x.sb * y.ti + x.len * y.htb;
	x.htab += x.ta * x.tb * y.ti + x.ta * y.htb + x.tb * y.hta + y.htab;
	x.hta += x.ta * y.ti + y.hta, x.htb += x.tb * y.ti + y.htb;
	x.sab += y.ta * x.sb + y.tb * x.sa + x.len * y.ta * y.tb;
	x.sa += x.len * y.ta, x.sb += x.len * y.tb, x.ta += y.ta, x.tb += y.tb, x.ti += y.ti;
}

void pup(int x) {
	tr[x].sab = tr[ls].sab + tr[rs].sab;
	tr[x].sa = tr[ls].sa + tr[rs].sa;
	tr[x].sb = tr[ls].sb + tr[rs].sb;
	tr[x].hsa = tr[ls].hsa + tr[rs].hsa;
	tr[x].hsb = tr[ls].hsb + tr[rs].hsb;
	tr[x].hsab = tr[ls].hsab + tr[rs].hsab;
}

void pdn(int x) {
	ptg(tr[ls], tr[x]), ptg(tr[rs], tr[x]);
	tr[x].ta = tr[x].tb = tr[x].ti = tr[x].hta = tr[x].htb = tr[x].htab = 0;
}

void build(int l, int r, int x) {
	tr[x].len = r - l + 1;
	if (l == r) return;
	build(l, mid, ls), build(mid + 1, r, rs);
}

void upd(int l, int r, int s, int t, int op, int c, int x) {
	if (s <= l && r <= t) return ptg(tr[x], tag((ull)(op ? 0 : c), (ull)(!op ? 0 : c), 0)), void();
	pdn(x);
	if (s <= mid) upd(l, mid, s, t, op, c, ls);
	if (t > mid) upd(mid + 1, r, s, t, op, c, rs);
	pup(x);
}

ull qry(int l, int r, int s, int t, int x) {
	if (s <= l && r <= t) return tr[x].hsab;
	pdn(x); ull res = 0;
	if (s <= mid) res += qry(l, mid, s, t, ls);
	if (t > mid) res += qry(mid + 1, r, s, t, rs);
	return res;
}

void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) cin >> b[i];
	cin >> m;
	for (int i = 1, l, r; i <= m; i++)
		cin >> l >> r, q[r].pb(mp(l, i));
	build(1, n, 1);
	for (int i = 1; i <= n; i++) {
		while (tp[0] && a[st[tp[0]][0]] < a[i]) upd(1, n, st[tp[0] - 1][0] + 1, st[tp[0]][0], 0, a[i] - a[st[tp[0]][0]], 1), tp[0]--;
		while (tp[1] && b[st[tp[1]][1]] < b[i]) upd(1, n, st[tp[1] - 1][1] + 1, st[tp[1]][1], 1, b[i] - b[st[tp[1]][1]], 1), tp[1]--;
		st[++tp[0]][0] = st[++tp[1]][1] = i, upd(1, n, i, i, 0, a[i], 1), upd(1, n, i, i, 1, b[i], 1);
		ptg(tr[1], tag(0, 0, 1));
		for (pi j : q[i]) ans[j.se] = qry(1, n, j.fi, i, 1);
	}
	for (int i = 1; i <= m; i++)
		cout << ans[i] << '\n';
}

bool Med;
signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cerr << (&Mbe - &Med) / 1048576.0 << " MB\n";
	#ifdef FILE
		freopen("match.in", "r", stdin);
		freopen("match.out", "w", stdout);
	#endif
	int T = 1;
	cin >> T, T = 1;
	while (T--) solve();
	cerr << (int)(1e3 * clock() / CLOCKS_PER_SEC) << " ms\n";
	return 0;
}
posted @ 2023-10-04 12:35  Ender_32k  阅读(47)  评论(0编辑  收藏  举报