http://codeforces.com/gym/103104
I. Sequence
题意:m 个限制条件:pindex=value。问有多少个四元组 (A,B,L,R) 满足 ∀i∈[A,B],pi 可以取 [L,R] 中任意数。1≤A,B,L,R≤N
单调栈
问题转化为二维网格上有 m 个坏点,问有几个只包含好点的矩形。
dp[i][j] 表示以 (i,j) 为右下端点的矩形的个数。
遍历行,遍历列,对每一行维护一个递增的单调栈,左上端点的取法等于栈顶的左上位置取法数+当前位置到栈顶位置构成的矩形中的点数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <bits/stdc++.h>
bool dbg = true; #define debug(x) if (dbg) cout << #x << ":\t" << (x) << endl; using namespace std; #define ll long long #define ull unsigned ll const int N = 5005; const int INF = 0x3f3f3f3f; const ll inf = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; const ll inv2 = (mod + 1) / 2; typedef pair<int, int> pii; typedef pair<int, ll> pil;
int n, m; int mz[N][N]; int a[N]; int st[N], tp; int dp[N][N];
int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)mz[i][j] = 1; for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); mz[x][y] = 0; } ll ans = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) if (!mz[i][j])a[j] = 0; else a[j]++; tp = 0; for (int j = 1; j <= n; j++) { while (tp && a[st[tp]] > a[j])tp--; if (tp)dp[i][j] = dp[i][st[tp]]; dp[i][j] += (j - st[tp]) * a[j]; ans += dp[i][j]; st[++tp] = j; } } printf("%lld\n", ans); return 0; }
|