zoukankan      html  css  js  c++  java
  • Codevs 1247 排排站

    1247 排排站

     

    USACO

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    FJ的N头奶牛有一些共同之处(1 <= N <= 100,000)。FJ可以将这N头奶牛通过K种特征来归类(1 <= K <= 30)。例如,一些奶牛表现出来的特征1可能是有斑点,特征2可能是较之于PASCAL更喜欢C,等等。

    FJ发明了一种简明的描述特征的方法——“特征码”,用一个长度为k的二进制串来表示这头牛的特征表现。例如,一头牛的“特征码”为13,转换为二进制就是1101,代表这头牛具有特征1、3、4 (从右读到左),但是不表现特征2。总的说来,如果这头奶牛表现特征i,那么我们在他的“特征码”的二进制的第i位就为1。

    FJ将奶牛排成了一个1..N的队列,他注意到一种确定的排列方法可以使奶牛们的表现更“平衡”。一个连续的i..j的范围平衡表示为如果K种特征都有同样多的奶牛来表现。FJ想知道他究竟可以排出一个多长的“平衡”队列。请帮助他。

    输入描述 Input Description

    第一行两个整数n和k

    接下来n行每行一个整数

    输出描述 Output Description

    一个整数表示最大的长度

    样例输入 Sample Input

    7 3 






    2

    样例输出 Sample Output

    4

    /*
        暴力,将所有特征数字转换为二进制后,存到a[][]数组里,然后竖着看,从每一头牛往下数,找以这头牛为起点的最大长度,这个暴力其实不用hash 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100010
    #define mod 12200717
    int n,m,a[maxn][40],h[maxn][40],ans;
    using namespace std;
    void change(int x){
        int z=1<<(m-1),y=a[x][0];
        for(int i=1;i<=m;i++){
            if(y-z>=0)y-=z,a[x][i]=1;
            else a[x][i]=0;
            z>>=1;
        }
    }
    void hash(int from,int len,int num){
        h[from][num]+=a[from+len-1][num];
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i][0]);
            change(i);
        }
        int now=0;
        for(int i=1;i<=n;i++){//起点 
            if(n-i+1<=ans)break;
            for(int j=1;j<=n-i+1;j++){//长度 
                int len=j;
                bool flag=0;
                hash(i,j,1);
                int st=h[i][1];
                for(int k=2;k<=m;k++){//每头牛的信息 
                    hash(i,j,k);
                    if(h[i][k]!=h[i][1]){
                        flag=1;
                    }
                }
                if(flag==0)ans=max(ans,len);
            }
        }
        printf("%d",ans);
    }
    40分 超时
    /*
    还是差分
    因为对于符合条件的序列
    有 sj0 - si0 = sj1 - si1 =...= sjk-1 - sik-1
    也就是说 如果存在i j 满足
      sj1 - sj0 == si1 - si0  
      sj2 - sj0 == si2 - si0  
           ......
      sjk-1 - sj0 == sik-1 - si0  
    我们定义c[i,j]=s[i,j]-s[i,0] 
    问题就转化成了 找隔得最远的ij 满足c[i] 和 c[j] 一样
    这里用hash加速查找 给每个c[i] 搞一个hash值 放到hash表里 
    坑死我了,if(r<0) r=-r,查错查了一个小时
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    using namespace std;
    #define mod 1000003
    int n,m,a[100010],sum[100010][50],b[100010][50],h[1000100],ans;
    int hash(int x){
        int r=0;
        for(int i=1;i<=m;i++)r=r%mod+b[x][i]<<2;
        if(r<0)r=-r;
        return r%mod;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int x;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            if((1<<(j-1))&a[i])sum[i][j]=sum[i-1][j]+1;
            else sum[i][j]=sum[i-1][j];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                b[i][j]=sum[i][j]-sum[i][1];
            }
        }
        memset(h,-1,sizeof(h));
        h[0]=0;
        for(int i=1;i<=n;i++){
            int k=hash(i);
            while(h[k]!=-1){
                int flag=0;
                for(int j=1;j<=m;j++){
                    if(b[h[k]][j]!=b[i][j]){flag=1;break;}
                }
                if(flag==0&&i-h[k]>ans){ans=i-h[k];break;}
                k++;
            }
            if(h[k]==-1)h[k]=i;
        }
        printf("%d",ans);
    }
    100分
  • 相关阅读:
    Linux 命令大全
    MySQL 存储 utf8mb4
    PHP房贷计算器代码,等额本息,等额本金
    laravel 原生 sql
    include_once 问题
    laravel count distinct
    微信小程序显示cms里的html文章
    PHP文件上传
    Ajax做无刷新分页
    PHP封装返回Ajax字符串和JSON数组
  • 原文地址:https://www.cnblogs.com/thmyl/p/7192867.html
Copyright © 2011-2022 走看看