zoukankan      html  css  js  c++  java
  • 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:
    ",++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
    ",dp[n-1]);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    MySQL-MMM方案
    MySQL双主复制
    MySQL主从复制
    Keepalived实现高可用
    CentOS7.2 部署Haproxy 1.7.2
    博客园写随笔时用数学公式
    Java中有三种移位运算符
    VS Code配置C/C++环境
    Visual Studio Code 如何编写运行 C、C++ 程序?
    头一次知道“原地算法”?!
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4555870.html
Copyright © 2011-2022 走看看