测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A17495. 图书馆

填空题 困难

题目描述

图书馆

题目描述

某城市有 n 条东西向街道和 n 条南北向街道,构成一个 n×n 的街区网格。每个交叉路口处恰好建有一座图书馆,且每一行、每一列的交叉路口都恰好有一座图书馆。已知第 i 座图书馆的坐标 (xi,yi) 表示它位于第 xi 条东西向街道与第 yi 条南北向街道的交汇处。

城市规划师想要知道:有多少个 正方形区域(由连续的若干条东西向街道和连续的若干条南北向街道围成),使得该区域内每一行、每一列也恰好各有一座图书馆?

输入格式

第一行,一个整数 n。

第二行,n 个整数 x1,x2,…,xn,表示第 i 座图书馆的东西向街道编号。

第三行,n 个整数 y1,y2,…,yn,表示第 i 座图书馆的南北向街道编号。

输入保证:1≤xi,yi≤n,且每行每列恰好只有一座图书馆。

输出格式

输出一个整数,表示满足条件的正方形区域个数。

输入样例

7
1 2 3 4 5 6 7
4 3 1 6 2 5 7

输出样例

10

说明提示

1≤n≤105

1≤xi,yi≤n

输入保证每行每列恰好有一座图书馆。

参考答案

#include <iostream> #include <vector> #include <stack> #include <algorithm> using namespace std; typedef long long ll; vector<int> a, leftBig, rightBig; ll total = 0; void dfs(int l, int r, int mid) { int maxVal = a[mid]; vector<int> minLeft, minRight; int mn = maxVal; minLeft.push_back(mn); for (int i = mid - 1; i >= l; i--) { mn = min(mn, a[i]); minLeft.push_back(mn); } mn = maxVal; minRight.push_back(mn); for (int i = mid + 1; i <= r; i++) { mn = min(mn, a[i]); minRight.push_back(mn); } int L = minLeft.size() - 1; int R = minRight.size() - 1; int i = 0, j = 0; while (i <= L && j <= R) { int curMin = min(minLeft[i], minRight[j]); if (maxVal - curMin == i + j) total++; if (i == L) j++; else if (j == R) i++; else if (minLeft[i+1] < minRight[j+1]) i++; else j++; } int lm = leftBig[mid], rm = rightBig[mid]; if (lm >= l) dfs(l, mid-1, lm); if (rm <= r) dfs(mid+1, r, rm); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> x(n), y(n); a.resize(n+2); leftBig.assign(n+2, 0); rightBig.assign(n+2, n+1); for (int i = 0; i < n; i++) cin >> x[i]; for (int i = 0; i < n; i++) cin >> y[i]; for (int i = 0; i < n; i++) a[x[i]] = y[i]; stack<int> st; for (int i = 1; i <= n; i++) { while (!st.empty() && a[st.top()] < a[i]) st.pop(); if (!st.empty()) leftBig[i] = st.top(); st.push(i); } while (!st.empty()) st.pop(); for (int i = n; i >= 1; i--) { while (!st.empty() && a[st.top()] < a[i]) st.pop(); if (!st.empty()) rightBig[i] = st.top(); st.push(i); } int root = 1; for (int i = 2; i <= n; i++) if (a[i] > a[root]) root = i; dfs(1, n, root); total += n; cout << total << endl; return 0; }
上一题 下一题