• HDU


    题目链接: Assignment

     题意:

      给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k。

    题解:

      RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相当于求出了每个区间的最大值-最小值。那么现在我们枚举左端点,二分右端点就可以在n×logn×logn的时间内过。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_N = 1e5+9;
     4 int vec[MAX_N];
     5 int dp1[MAX_N][25];
     6 int dp2[MAX_N][25];
     7 long long ans = 0;
     8 int N,M,T;
     9 void ST(int N)
    10 {
    11     for(int i=1;i<=N;i++) dp1[i][0] = dp2[i][0] = vec[i];
    12     for(int j=1;(1<<j)<=N;j++)
    13     {
    14         for(int i=1;i+(1<<j)-1<=N;i++)
    15         {
    16             dp1[i][j] = max(dp1[i][j-1],dp1[i+(1<<j-1)][j-1]);
    17             dp2[i][j] = min(dp2[i][j-1],dp2[i+(1<<j-1)][j-1]);
    18         }
    19     }
    20 }
    21 int RMQ(int l,int r)
    22 {
    23     int k = 0;
    24     while(1<<k+1 <= r-l+1) k++;
    25     int maxn = max(dp1[l][k],dp1[r-(1<<k)+1][k]);
    26     int minn = min(dp2[l][k],dp2[r-(1<<k)+1][k]);
    27     return maxn-minn;
    28 }
    29 int main()
    30 {
    31     cin>>T;
    32     while(T--)
    33     {
    34         cin>>N>>M;
    35         ans = 0;
    36         for(int i=1;i<=N;i++) scanf("%d",&vec[i]);
    37         ST(N);
    38         for(int i=1;i<=N;i++)
    39         {
    40             int l =i,r = N;
    41             while(l<=r)
    42             {
    43                 int mid = (l+r)>>1;
    44                 if(RMQ(i,mid) < M) l = mid+1;
    45                 else r = mid-1;
    46             }
    47             ans += (l-1) - i +1;
    48         }
    49         cout<<ans<<endl;
    50     }
    51     return 0;
    52 }
    View Code

      还有一种解法是用两个单调队列维护区间的最大和最小值,让我收益颇多@。@!用双端队列构成单调队列,一个维护最大值,一个维护最小值,从左向右枚举右端点。现在我们知道了这个区间的最大值和最小值,如果最大值减去最小值是小于k的则当前的左端点到右端点里面所有的区间都是符合条件的。直到枚举到一个右端点,使得最大值减最小值>=k,则开始移动左端点删去两个队列中左端点的值(如果有的话),直到区间重新符合条件。用单调队列处理的话复杂度为(O(n))。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_N = 1e5+9;
     4 long long vec[MAX_N];
     5 deque<long long> que1,que2;
     6 int main()
     7 {
     8     long long N,M,T;
     9     cin>>T;
    10     while(cin>>N>>M)
    11     {
    12         while(!que1.empty()) que1.pop_back();
    13         while(!que2.empty()) que2.pop_back();
    14         for(int i=0;i<N;i++) scanf("%lld",&vec[i]);
    15         int pos = 0;
    16         long long ans = 0;
    17         for(int i=0;i<N;i++)
    18         {
    19             while(!que1.empty() && que1.back() < vec[i]) que1.pop_back();
    20             que1.push_back(vec[i]);
    21             while(!que2.empty() && que2.back() > vec[i]) que2.pop_back();
    22             que2.push_back(vec[i]);
    23             while(!que1.empty() && !que2.empty() && que1.front() - que2.front() >= M)
    24             {
    25                 ans += (i-pos);
    26                 if(que1.front() == vec[pos]) que1.pop_front();
    27                 if(que2.front() == vec[pos]) que2.pop_front();
    28                 pos++;
    29             }
    30         }
    31         while(pos < N)
    32         {
    33             ans += (N-pos);
    34             pos ++;
    35         }
    36         cout<<ans<<endl;
    37     }
    38     return 0;
    39 }
    View Code
  • 相关阅读:
    FastReport.Net使用:[13]如何使用表达式
    FastReport.Net使用:[11]公共对象属性介绍
    FastReport.Net使用:[10]报表栏目说明
    FastReport.Net使用:[9]多栏报表(多列报表)
    FastReport.Net使用:[8]交叉表一
    FastReport.Net使用:[7]打印空白行
    FastReport.Net使用:[6]HTML标签使用
    测试,测试开发,QA,QM,QC--------- 测试之路勿跑偏
    java 接口自动化测试之数据请求的简单封装
    java HttpClient POST请求
  • 原文地址:https://www.cnblogs.com/doggod/p/8401405.html
Copyright © 2020-2023  润新知