hdu 5289 Assignment(给一个数组,求有多少个区间,满足区间内的最大值和最小值之差小于k)

1.区间是一段的,不是断开的哟

2.代码是看着标程写的

3.枚举左端点,二分右端点流程:

#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int N=200007;
int minn[N][20];//2^18=262144   2^20=1048576
int maxx[N][20];

//----------------------查询O(1)-------------
int queryMin(int l,int r)
{
    int k=floor(log2((double)(r-l+1)));//2^k <= (r - l + 1),floor()向下取整函数
    return Min(minn[l][k],minn[r-(1<<k)+1][k]);
}

int queryMax(int l,int r)
{
    int k=floor(log2((double)(r-l+1)));
    return Max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}
//-------------------------------------------------

int calc(int l,int r)
{
    int k=log2((double)(r-l+1));
    int MAX=Max(maxx[l][k],maxx[r-(1<<k)+1][k]);
    int MIN=Min(minn[l][k],minn[r-(1<<k)+1][k]);
    return MAX-MIN;
}

int main()
{
    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);
            minn[i][0]=maxx[i][0]=j;
        }
//------------------------------------------预处理O(nlogn)---------------
        for(j=1; (1<<j)<=n; ++j)//1<<j==2^j,枚举区间长度1,2,4,8,16,,,,,
            for(i=1; i+(1<<j)-1<=n; ++i)//i+(1<<j)-1表示区间右边界,枚举区间左边界
            {
                p=(1<<(j-1));
                minn[i][j]=Min(minn[i][j-1],minn[i+p][j-1]);
                maxx[i][j]=Max(maxx[i][j-1],maxx[i+p][j-1]);
            }
//-----------------------------------------------------------------------

//---------------------------枚举左端点,二分右端点---------------------------

        int l,r,mid;
        ans=0;
//左端点固定为i,右端点用l,r,mid去确定,最后用l和r中的其中一个,此时l+1==r
        for(i=1; i<=n; ++i)
        {
            l=i,r=n;
            while(l+1<r)
            {
                mid=(l+r)>>1;//(l+r)/2==(l+r)>>1
                if(calc(i,mid)<k)
                {
                    l=mid;
                }
                else
                {
                    r=mid-1;//自己去演示算法流程就知道r可以赋值mid-1
                }
            }
            if(calc(i,r)<k)
            {
                ans=ans+(LL)(r-i+1);
            }
            else
            {
                ans=ans+(LL)(l-i+1);
            }
        }
//---------------------------------------------------------------------------
        printf("%lld\n",ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 13:09:44

hdu 5289 Assignment(给一个数组,求有多少个区间,满足区间内的最大值和最小值之差小于k)的相关文章

剑指Offer(Java版)第四十题:在数组中的两个数字,如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。 并将P对1000000007取模的结果输出。 即输出P%1000000007

/*在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000000007 */ import java.util.*; public class Class40 { public int InversePairs(int[] array){ int length = array.length; int P = 0; for(int i = 0; i < lengt

计算数组中最大值和最小值的差值

算法一 <?php /** * 获取数组中最大值和最小值的差值 */ function getDiffVal($arr) { $max = 0; $min = 0; foreach($arr as $k=>$v) { // 赋初值 if ($k == 0) { $max = $min = $v; } // 获取最大值 if ($v > $max) { $max = $v; } // 获取最小值 if ($v < $min) { $min = $v; } } $diff = $max

HDU 5289 Assignment(二分+RMQ-ST)

Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 3813    Accepted Submission(s): 1771 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered

hdu 5289 Assignment 二分+rmq

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 332    Accepted Submission(s): 169 Problem Description Tom owns a company and he is

HDU 5289 Assignment(多校2015 RMQ 单调(双端)队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special tas

HDU 5289 Assignment(RMQ 单调(双端)队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special tas

hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 题意:给你n个数和k,求有多少的区间使得区间内部任意两个数的差值小于k,输出符合要求的区间个数 思路:求出区间的最大最小值,只要他们的差值小于k,那么这个区间就符合要求,但是由于n较大,用暴力一定超时,所以就要用别的方法了:而RMQ是可以求区间的最值的,而且预处理的复杂度只有O(nlogn),而查询只是O(1)处理,这样相对来说节约了时间,再根据右端点来二分枚举左端点(其实不用二分好像更快,估

HDU 5289 Assignment(单调队列)

Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 297    Accepted Submission(s): 152 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro

HDU 5249 离线树状数组求第k大+离散化

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1160    Accepted Submission(s): 488 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的