码迷,mamicode.com
首页 > 其他好文 > 详细

CODEFORCES #526 F. Pudding Monsters

时间:2016-08-16 23:51:09      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:

题目描述:

给出一个 N * N 的矩阵,每一行、每一列,有且仅有一个特殊点。问有多少个K * K的矩阵内恰好有K个特殊点。

解题思路:

转换下模型,矩阵可以看成一个N的排列,求的是有多少连续子序列中的数是一个区间中连续的,也就是最大数减最小数等于长度减一。那么我们就可以考虑分治解决,对于跨过分治点m的情况的,可以分两大类考虑,最值各在分治点一侧、同在分治点一侧。第一种,可以直接枚举一侧长度,就能计算出另一侧长度,在判断是否合法。第二种,假如i在左,j在右,一种情况是max[j] - min[i] = i - j,那么可以变成max[j] + j = min[i] + i,因为max和min都是单调的,所以可以用单调队列和桶维护。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define i64 long long
 5 using namespace std;
 6 
 7 const int N = 5e4 + 10;
 8 int n, s[N], mn[N], mx[N], sum[N * 2];
 9 i64 ans;
10 
11 void divide(int l, int r) {
12     if (l == r) return;
13     int mid = l + r >> 1;
14     divide(l, mid);
15     divide(mid + 1, r);
16     mn[mid] = mx[mid] = s[mid];
17     mn[mid + 1] = mx[mid + 1] = s[mid + 1];
18     for (int i = mid - 1; i >= l; i --) mn[i] = min(s[i], mn[i + 1]), mx[i] = max(s[i], mx[i + 1]);
19     for (int i = mid + 2; i <= r; i ++) mn[i] = min(s[i], mn[i - 1]), mx[i] = max(s[i], mx[i - 1]);
20     for (int i = mid; i >= l; i --) {
21         int j = mx[i] - mn[i] + i;
22         if (j > mid && j <= r && mx[j] < mx[i] && mn[j] > mn[i]) ans ++;
23     }
24     for (int j = mid + 1; j <= r; j ++) {
25         int i = j - mx[j] + mn[j];
26         if (i >= l && i <= mid && mx[j] > mx[i] && mn[j] < mn[i]) ans ++;
27     }
28     int hea, tai; 
29     hea = tai = mid + 1;
30     for (int i = mid; i >= l; i --) {
31         while (tai <= r && mn[tai] > mn[i]) ++ sum[mx[tai] - tai + n], ++ tai;
32         while (hea < tai && mx[hea] < mx[i]) -- sum[mx[hea] - hea + n], ++ hea;
33         ans += (i64)sum[mn[i] - i + n];
34     }
35     while (hea < tai) -- sum[mx[hea] - hea + n], ++ hea;
36     hea = tai = mid;
37     for (int j = mid + 1; j <= r; j ++) {
38         while (hea >= l && mn[hea] > mn[j]) ++ sum[mx[hea] + hea], -- hea;
39         while (tai > hea && mx[tai] < mx[j]) -- sum[mx[tai] + tai], -- tai;
40         ans += (i64)sum[mn[j] + j];
41     }
42     while (tai > hea) -- sum[mx[tai] + tai], -- tai;
43 }
44 
45 int main() {
46     ans = 3e10;
47     scanf("%d", &n);
48     for (int i = 1; i <= n; i ++) {
49         int x, y;
50         scanf("%d %d", &x, &y);
51         s[x] = y;
52     }
53     divide(1, n);
54     printf("%lld", ans + (i64)n);
55     return 0;
56 }

 

CODEFORCES #526 F. Pudding Monsters

标签:

原文地址:http://www.cnblogs.com/awner/p/5778095.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!