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

HDU 5289

时间:2015-08-03 22:24:33      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

题意:给你一个序列,求有多少区间 满足 区间最大值,最小值的差小于K

思路:   ST处理最大最小, 枚举起点,二分终点,计算值

(先贴个标程,自己写的无限WA…)

#include<cstdio>
#include<cstring>
#include<cmath>
#define LL __int64
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
const int N = 200007;
int min[N][20];
int max[N][20];
int queryMin(int l,int r){
    int k=log2((double)(r-l+1));
    return Min(min[l][k],min[r-(1<<k)+1][k]);
}
int queryMax(int l,int r){
    int k=log2((double)(r-l+1));
    return Max(max[l][k],max[r-(1<<k)+1][k]);
}
int calc(int l,int r){
    int k=log2((double)(r-l+1));
    int MAX=Max(max[l][k],max[r-(1<<k)+1][k]);
    int MIN=Min(min[l][k],min[r-(1<<k)+1][k]);
    return MAX-MIN;
}
char filein[]={"9.in"};
char fileot[]={"9.out"};
int main(){
//    for(int t=0;t<10;++t){
//    filein[0]=t+‘0‘;
//    fileot[0]=t+‘0‘;
//    freopen(filein,"r",stdin);
//    freopen(fileot,"w",stdout);
    int T;
    int n,k,i,j,p;
    LL ans;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        for(i=1;i<=n;++i){
            scanf("%d",&j);
            min[i][0]=max[i][0]=j;
        }
        for(j=1;(1<<j)<=n;++j)
        for(i=1;i+(1<<j)-1<=n;++i){
            p=(1<<(j-1));
            min[i][j]=Min(min[i][j-1],min[i+p][j-1]);
            max[i][j]=Max(max[i][j-1],max[i+p][j-1]);
        }
        int l,r;
        ans=0;
        for(i=1;i<=n;++i){
            l=i,r=n;
            while(l+1<r){
                p=(l+r)>>1;
                if(calc(i,p)<k){
                    l=p;
                }
                else{
                    r=p;
                }
            }
            if(calc(i,r)<k){
                p=r;
                ans=ans+(LL)(r-i+1);
            }
            else{
                p=l;
                ans=ans+(LL)(l-i+1);
            }
        }
        printf("%I64d\n",ans);
    }
//    fclose(stdin);
//    fclose(stdout);
//    }
    return 0;
}

(自己 WA

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int dmax[100001][30];
int dmin[100001][30];
vector<int> Line;
void RMQ_max(const vector<int>& A) {
    int n = A.size();
    for(int i = 0; i < n; ++i) dmax[i][0] = A[i];
    for(int j = 1; (1<<j) <= n; ++j) 
        for(int i = 0; i + (1<<j) - 1 < n; ++i)
        dmax[i][j] = max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]);
}
int RMQmax(int L,int R) {
    int k = 0;
    while((1<<(k+1)) <= (R-L+1)) k++;
    return max(dmax[L][k],dmax[R-(1<<k)+1][k]);
} 
//Min
void RMQ_min(const vector<int>& A) {
    int n = A.size();
    for(int i = 0; i < n; ++i) dmin[i][0] = A[i];
    for(int j = 1; (1<<j) <= n; ++j) 
        for(int i = 0; i + (1<<j) - 1 < n; ++i)
        dmin[i][j] = min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]);
}
int RMQmin(int L,int R) {
    int k = 0;
    while((1<<(k+1)) <= (R-L+1)) k++;
    return min(dmin[L][k],dmin[R-(1<<k)+1][k]);
} 
int main() {
    int t,n,num,k;
    scanf("%d",&t);
    while(t--) {
        Line.clear();
        scanf("%d %d",&n,&k);
        for(int i = 0; i <n; ++i) {
            scanf("%d",&num);
            Line.push_back(num);
        }
        int L,R;
        RMQ_max(Line);
        RMQ_min(Line);
        __int64 ans = 0;
        for(int i = 0; i < n; ++i) {
            int l = i, r = n-1;
            while(l + 1< r) {
                int m = (l + r + 1) >> 1;
                int Min = RMQmin(l,m);
                int Max = RMQmax(l,m);
                if(Max - Min < k) l = m;
                else r = m;
            }
            if(RMQmax(i,r) - RMQmin(i,r) < k) ans +=(__int64) (r-i+1);
            else ans +=(__int64) (l-i+1);
        } 
        printf("%I64d\n",ans);
    }
}

HDU 5289

标签:

原文地址:http://www.cnblogs.com/aoxuets/p/4700423.html

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