• 玲珑杯”ACM比赛 Round #19 B 维护单调栈


    1149 - Buildings

    Time Limit:2s Memory Limit:128MByte

    Submissions:588Solved:151

    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 integers n(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].
    题意:给你一个长度为n的序列 问有多少区间 使得 区间最大值-区间最小值<=k
    题解:单调栈处理出以a[i]为最小值的区间左界右界  组合出合法的区间 注意 (同一左界右界)或者称为同一块 下的最小值可能会有重复
    从左向右遍历时 将当前值的左界改为(同一块中上一个相同值的位置+1) 具体看代码;
     1 #pragma comment(linker, "/STACK:102400000,102400000")
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <cmath>
     8 #include <cctype>
     9 #include <map>
    10 #include <set>
    11 #include <queue>
    12 #include <bitset>
    13 #include <string>
    14 #include <complex>
    15 #define ll long long
    16 #define mod 1000000007
    17 using namespace std;
    18 ll n,k;
    19 ll a[200005];
    20 ll l[200005],r[200005];
    21 map<ll,map<ll,ll>> mp;
    22 int main()
    23 {
    24         scanf("%lld %lld",&n,&k);
    25         for(int i=1; i<=n; i++)
    26             scanf("%lld",&a[i]);
    27         a[0]=-1ll;
    28         a[n+1]=-1ll;
    29         l[1]=1ll;
    30         for(int i=2; i<=n; i++) //关键********
    31         {
    32             ll temp=i-1;
    33             while(a[temp]>=a[i])//维护一个递增的序列
    34                 temp=l[temp]-1;
    35             l[i]=temp+1;
    36         }
    37         r[n]=n;
    38         for (int i=n-1; i>=1; i--)
    39         {
    40             ll temp=i+1;
    41             while(a[temp]>=a[i])
    42                 temp=r[temp]+1;
    43             r[i]=temp-1;
    44         }
    45         ll ans=0;
    46         for(int i=1; i<=n; i++)
    47         {
    48             ll x=0,y=0;
    49             if(mp[l[i]][r[i]]!=0){//去重 更改l[i]
    50               ll now=l[i];
    51               l[i]=mp[l[i]][r[i]];
    52               mp[now][r[i]]=i+1;
    53              }
    54              else
    55             mp[l[i]][r[i]]=i+1;
    56             for(int j=i-1; j>=l[i]; j--)
    57             {
    58                 if((a[j]-a[i])<=k)
    59                     x++;
    60                 else
    61                     break;
    62             }
    63             for(int j=i+1; j<=r[i]; j++)
    64             {
    65                 if((a[j]-a[i])<=k)
    66                     y++;
    67                 else
    68                     break;
    69             }
    70             ans=ans+x*y+x+y+1ll;
    71         }
    72         printf("%lld
    ",ans);
    73     return 0;
    74 }
     
  • 相关阅读:
    模拟实现链表
    模拟实现内存操作函数
    实现一个简单的进度条
    简单的通讯录(C语言实现)
    sizeof和strlen
    动态联编
    不用第三个变量交换两个变量的值
    内存对齐
    字符串指针和字符数组的区别
    vs中的一些bug解决
  • 原文地址:https://www.cnblogs.com/hsd-/p/7256514.html
Copyright © 2020-2023  润新知