您的位置:首页 > 其它

codeforces基础题——#361(div2)D

2016-09-08 20:15 429 查看

#361(Div 2) D

题目大意 :给你a, b两个长度为n的整数序列(1 <= n <= 200000), 问有多少个(l, r)(1  <= l, r  <=  n )使得a中区间(l, r)的最大值与b中区间(l, r)的最小值一样

题解 : 一开始在想神奇的树状数组瞎搞做法, 其实可以做, 但写起来很麻烦, 于是写到一半太累(懒)了, 就没再写……
此题正解十分简洁, 枚举左端点l,然后找右端点r的可行位置, 我们发现如果从i 到 i + j可行, 而i + j + 1不可行, 那么在之后应定不会有可行的右端点, 因为a中区间最大值只会增加, 而b中区间的最小值只会减少, 所以右端点r的可行位置一定在一段连续的区间中。那么怎找到这段区间呢, 注意左端点确定时,最大值与最小值具有单调性, 所以如果我们利用RMQ欲处理出最大值和最小值, 就能二分把区间找到,具体如下:
如果a中(l, mid)大于b中(l, mid)的值, 那么(mid + 1, r)的值一定是不合法的, 所以查找区间(l, mid), 合法的值一定在(mid + 1, r)中, 查找(mid +1, r);
通过比较大于和大于等于找出区间的左端点和右端点, 更新答案(然而我这里之前没想通,  wa了几百次)
所以RMQ预处理, 暴力枚举l, 二分r可行区间即可, 时间复杂度O(nlogn)


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[200100], b[200100], n;
int st1[200100][21], st2[200100][21], p[21], lg[200100];
int rmq1(int i, int j)
{
int k = lg[j - i + 1];
return max(st1[i][k], st1[j - p[k] + 1][k]);
}
int rmq2(int i, int j)
{
int k = lg[j - i + 1];
return min(st2[i][k], st2[j - p[k] + 1][k]);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++)scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++)scanf("%d", &b[i]);
int tmp = 2;p[0] = 1;
for (int i = 1; i <= 20; i ++) p[i] = p[i - 1] * 2;
for (int i = 2; i <= n; i ++) {
lg[i] = lg[i - 1];
if (tmp <= i) lg[i] ++, tmp *= 2;
//printf("%d %d\n", i, lg[i]);
}
for (int i = 1; i <= n; i ++) st1[i][0] = a[i], st2[i][0] = b[i];
for (int i = 1; i <= 20 && p[i] <= n; i ++)
for (int j = 1; j <= n && j + p[i] - 1 <= n; j ++){
st1[j][i] = max(st1[j][i - 1], st1[j + p[i - 1]][i - 1]);
st2[j][i] = min(st2[j][i - 1], st2[j + p[i - 1]][i - 1]);
}

long long ans = 0;
for (int i = 1; i <= n; i ++){
if (a[i] > b[i]) continue;
int l = i, r = n;
while(l != r){

int mid = (l + r) >> 1;
if (rmq1(i, mid) >= rmq2(i, mid)) r = mid;
else l = mid + 1;
}
if (rmq1(i, r) != rmq2(i, l)) continue;
int p = l;
l = i, r = n + 1;
while(l != r){
int mid = (l + r) >> 1;
if (rmq1(i, mid) > rmq2(i, mid)) r = mid;
else l = mid + 1;//printf("%d %d\n", l, r);
}
ans += l - p;
//
}
printf("%I64d\n", ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: