“玲珑杯”ACM比赛 Round #19 B.Buildings【二分+RMQ】

来源:互联网 发布:psp马甲卡淘宝 编辑:程序博客网 时间:2024/05/21 06:50

1149 - Buildings

Time Limit:2s Memory Limit:128MByte

Submissions:617Solved:159

DESCRIPTION

There are nn buildings lined up, and the height of the ii-th house is hihi.

An inteval [l,r][l,r](lr)(l≤r) is harmonious if and only if max(hl,,hr)min(hl,,hr)kmax(hl,…,hr)−min(hl,…,hr)≤k.

Now you need to calculate the number of harmonious intevals.

INPUT
The first line contains two integersn(1n2×105),k(0k109)n(1≤n≤2×105),k(0≤k≤109).The second line contains nn integers hi(1hi109)hi(1≤hi≤109).
OUTPUT
Print a line of one number which means the answer.
SAMPLE INPUT
3 1
1 2 3
SAMPLE OUTPUT
5
HINT
Harmonious intervals are: [1,1],[2,2],[3,3],[1,2],[2,3][1,1],[2,2],[3,3],[1,2],[2,3].
SOLUTION
“玲珑杯”ACM比赛 Round #19


题目大意:


给你一个长度为N的序列,求有多少个区间,使得区间内最大值-最小值<=k;


思路:


我们知道,如果我们确定了左端点L的话,随着右端点R的增加,会使得最大值越来越大,最小值越来越小,也就是差会越来越大,所以我们这里包含一个单调性。

我们可以O(n)枚举左端点,然后二分右端点然后RMQ预处理能够查询区间的最大值和最小值。

过程维护一个最终位子Pos,那么Pos-L+1就是当前左端点对答案的贡献。


Ac代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cmath>using namespace std;int maxsum[250000][30];int minsum[250000][30];int a[250000];int n,k;void rmq_init(){    for(int j = 1; (1<<j) <= n; ++j)        for(int i = 1; i + (1<<j) - 1 <= n; ++i)        {            maxsum[i][j] = max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);            minsum[i][j] = min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);        }}int Get_cha(int l, int r){    int k = log2(r-l+1);    int Max = max(maxsum[l][k], maxsum[r-(1<<k)+1][k]);    int Min = min(minsum[l][k], minsum[r-(1<<k)+1][k]);    return Max - Min;}int main(){    while(~scanf("%d%d",&n,&k))    {        for(int i = 1; i <= n;++i)        {            scanf("%d",&a[i]);            maxsum[i][0] = a[i];             minsum[i][0] = a[i];        }        rmq_init();        long long  ans = 0;        int l , r;        for(int i = 1; i <= n; ++i)        {            int l=i;            int r=n;            int pos=-1;            while(r-l>=0)            {                int mid=(l+r)/2;                if(Get_cha(i,mid)<=k)                {                    pos=mid;                    l=mid+1;                }                else r=mid-1;            }            ans += pos - i+1;        }        printf("%lld\n",ans);    }}













原创粉丝点击