题解:CF2163C Monopati
官解怎么在双指针,不会啊呜呜。
首先一个很自然的想法是,因为 down-right path 只有
实现部分,设
但是你很快会发现,一个
其实不需要。发现实际上矩形的左边界和上边界实际上是固定的,我们只需要记录右下角
不是我想要的矩形,直接去掉。去掉被包含矩形的实现与去掉被包含区间(去掉子集和去掉超集都考的很多,甚至下一题就又考一遍)类似,可以直接用单调栈维护,先对横坐标排序,栈顶元素小于等于当前元素就一直弹出栈顶,然后当前元素入栈。具体实现可以参考 AC Code。
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define x first
#define y second
typedef long long ll;
typedef std::pair<int, int> pii;
ll read() {ll x; scanf("%lld", &x); return x;}
using std::min, std::max;
const int N = 214514;
int n, a[2][N];
pii pre[N], suf[N], p[N];
int main() {
int T = read(); while(T--) {
n = read();
rep(i, 0, 1) rep(j, 1, n) a[i][j] = read();
pre[1] = {a[0][1], a[0][1]};
rep(i, 2, n) {
pre[i].x = min(a[0][i], pre[i - 1].x);
pre[i].y = max(a[0][i], pre[i - 1].y);
}
suf[n] = {a[1][n], a[1][n]};
for(int i = n - 1; i; i--) {
suf[i].x = min(a[1][i], suf[i + 1].x);
suf[i].y = max(a[1][i], suf[i + 1].y);
}
rep(i, 1, n) {
p[i].x = min(suf[i].x, pre[i].x),
p[i].y = max(suf[i].y, pre[i].y);
}
std::sort(p + 1, p + n + 1);
ll ans = 0;
std::stack<pii> st;
rep(i, 1, n) {
while(!st.empty() && st.top().y >= p[i].y) st.pop();
st.push(p[i]);
}
int r = 2 * n + 1;
while(!st.empty()) {
auto [x, y] = st.top(); st.pop();
ans += x * /**/1ll * (r - y);
r = y;
}
printf("%lld\n", ans);
}
}