2015 Multi-University Training Contest 1(HDOJ5288、5289)

官方题解:http://blog.sina.com.cn/duoxiao2015


第一场开始时都还没放暑假。。。队友用我感觉会超时的代码AC了两题,囧。。。


HDOJ5288

题意:给一个序列,求共有多少个找不到任意两个不同数是整除关系的连续子序列,结果mod 1e9+7

思路:见官方题解O(nsqrt(n))的算法,但是没看懂,然后下图是大牛给我的解说,看完就懂了

2015 Multi-University Training Contest 1(HDOJ5288、5289)_第1张图片

PS:O(n^2)肯定会超时,但是数据太水,队友用O(n^2)的方法过了,就不贴代码了


HDOJ5289

题意:给一个长度为n的序列,为共有多少给连续子序列中最大值与最小值之差小于k

思路:一看到这题,我就想去用O(nlogn)的RMQ+二分,先RMQ预处理,然后对于每个起始位置二分查找结束位置

PS:赛后想起可以用O(n)单调队列直接扫一遍就可以了

PS2:O(n^2)肯定会超时,但是数据太水,队友居然又用O(n^2)的方法过了!!!

PS3:大白书P198页的RMQ的代码有误,害我RE了几次

以下是我写的RMQ+二分的代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
const int MAXN=100000+10;
const int MOD=1e9+7;

int dmax[MAXN][20],dmin[MAXN][20],a[MAXN];
int T,n,kk;

//输入外挂
template <class T>
inline bool read(T &ret) {
   char c; int sgn;
   if(c=getchar(),c==EOF) return 0; //EOF
   while(c!='-'&&(c<'0'||c>'9')) c=getchar();
   sgn=(c=='-')?-1:1;
   ret=(c=='-')?0:(c-'0');
   while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
   ret*=sgn;
   return 1;
}

void RMQ_init(){
    for(int i=1;i<=n;i++)
        dmax[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        dmax[i][j]=max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]);

    for(int i=1;i<=n;i++)dmin[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;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 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]);
}

int RMQ(int l,int r){
    return RMQmax(l,r)-RMQmin(l,r);
}

int bSearch(int x){
    int l=x,r=n;
    while(l<=r){
        int m=(l+r)>>1;
        if(RMQ(x,m)<kk)l=m+1;
        else r=m-1;
    }
    return r;
}

LL work(){
    LL res=0;
    for(int i=1;i<=n;i++){
        int j=bSearch(i);
        res+=j-i+1;
    }
    return res;
}

int main(){
#ifdef DEBUG
   freopen("CBin.txt","r",stdin);
   //freopen("CBout.txt","w",stdout);
#endif
    read(T);
    while(T--){
        read(n);
        read(kk);
        for (int i=1;i<=n;++i)read(a[i]);
        RMQ_init();
        cout<<work()<<"\n";
    }
    return 0;
}



你可能感兴趣的:(2015 Multi-University Training Contest 1(HDOJ5288、5289))