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

来源:互联网 发布:人工智能天使轮 编辑:程序博客网 时间:2024/06/07 01:41

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


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


HDOJ5288

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

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


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;}



0 0