HDU_5247(15百度之星B题)

做法:dp[i] = dp[i-1] + (i-k+1...i这段符合+1,否则+0)。如何判断这一段符不符合,找出这段的最大值,最小值,如何差值==k-1,并且里面的数没有重复,那么就可以+1,否则,就不能+1。最大值最小值用RMQ预处理一下是nlogn的复杂度,然后查找操作,因为长度一定所以就是o(1),问题的关键就是如何判断这个区间里面是否有重复的数,(n*k)的复杂度水过去的。。。,rep[i][j]表示i-j+1...i这个串是否有重复的,那么rep[i][j] = rep[i-1][j-1] || rep[i][j-1] || (num[i] == num[i-j+1]) 。然后就直接写了,然而我比赛搞了一半去装电脑去了。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#define FOR(i,x,y)  for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)

using namespace std;

int n,m,k,k_tw;
int num[11111];
int maxx[11111][15],minx[11111][15];
int dp[11111];
bool rep[11111][1111];

void INIT_RMQ(int bit){
    FOR(i,0,n){
        maxx[i][0] = minx[i][0] = num[i];
    }
    FOR(j,1,bit+1){
        IFOR(i,n-1,-1){
            if((i+(1<<(j-1))) < n){
                maxx[i][j] = max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
                minx[i][j] = min(minx[i][j-1],minx[i+(1<<(j-1))][j-1]);
            }
        }
    }
    FOR(i,0,n)  rep[i][1] = 0;
    FOR(j,2,1002){
        FOR(i,j-1,n){
            if(rep[i-1][j-1] || rep[i][j-1] || num[i] == num[i-j+1]){
                rep[i][j] = 1;
                continue;
            }
            rep[i][j] = 0;
        }
    }
}

void solve(){
    if(rep[k-1][k] || max(maxx[0][k_tw],maxx[k-(1<<k_tw)][k_tw])-min(minx[0][k_tw],minx[k-(1<<k_tw)][k_tw]) != k-1)    dp[k-1] = 0;
    else dp[k-1] = 1;
    FOR(i,k,n){
        dp[i] = dp[i-1];
        if(!rep[i][k] && max(maxx[i-k+1][k_tw],maxx[i+1-(1<<k_tw)][k_tw])-min(minx[i-k+1][k_tw],minx[i+1-(1<<k_tw)][k_tw]) == k-1){
            dp[i]++;
        }
    }
}

int main()
{
    //freopen("test.in","r",stdin);
    int tCase = 0;
    while(~scanf("%d%d",&n,&m)){
        printf("Case #%d:\n",++tCase);
        FOR(i,0,n)  scanf("%d",&num[i]);
        int tem = 0;
        while((1<<tem) < n){
            tem++;
        }
        tem--;
        INIT_RMQ(tem);
        FOR(i,0,m){
            scanf("%d",&k);
            k_tw = 0;
            while((1 << k_tw) <= k){
                k_tw ++;
            }
            k_tw--;
            solve();
            printf("%d\n",dp[n-1]);
        }
    }
    return 0;
}


posted @ 2015-05-31 01:06  hqwhqwhq  阅读(125)  评论(0编辑  收藏  举报