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


  • 相关阅读:
    LeetCode 40. 组合总和 II(Combination Sum II)
    LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
    LeetCode 60. 第k个排列(Permutation Sequence)
    LeetCode 47. 全排列 II(Permutations II)
    LeetCode 46. 全排列(Permutations)
    LeetCode 93. 复原IP地址(Restore IP Addresses)
    LeetCode 98. 验证二叉搜索树(Validate Binary Search Tree)
    LeetCode 59. 螺旋矩阵 II(Spiral Matrix II)
    一重指针和二重指针
    指针的意义
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4555870.html
Copyright © 2011-2022 走看看