zoukankan      html  css  js  c++  java
  • 【BZOJ】1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

    【题意】给定n头牛,k个特色,给出每头牛拥有哪些特色的二进制对应数字,[i,j]平衡当且仅当第i~j头牛的所有特色数量都相等,求最长区间长度。

    【算法】平衡树+数学转化

    【题解】统计前缀和sum[i][j]表示前i头牛特色为j的数量,则区间i~j平衡需要满足:

    sum[j][1]-sum[i-1][1]=sum[j][2]-sum[i-1][2]=sum[j][3]-sum[i-1][3]=...

    移项可得,只须

    sum[j][1]-sum[j][2]=sum[i-1][1]-sum[i-1][2]

    sum[j][1]-sum[j][3]=sum[i-1][1]-sum[i-1][3]

    所以,我们将所有前缀和sum[i][k]-=sum[i][1],那么区间i~j平衡只须sum[i-1][k]=sum[j][k],k=1~maxk。

    动态寻找数字可以用平衡树实现,因为是找相等,map最方便。

    另外,这类通过数学公式变换优化的例子十分常见,思考中将数学公式列出来有助于进一步发现数学特征。

    注意:最开始把0加进来!

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<map>
    #define ul unsigned long long
    using namespace std;
    const int maxn=100010,base=2334; 
    map<ul,int>q;
    int n,k,ans,sum[50];
    ul find(){
        ul s=0;
        for(int i=1;i<k;i++)s=s*base+sum[i]-sum[0];
        return s;
    }
    int main(){// 
        scanf("%d%d",&n,&k);
        int u;ul v;
        q[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&u);
            for(int j=0;j<k;j++)if(u&(1<<j))sum[j]++;
            v=find();//printf("[%d]%lld
    ",i,v);
            if(q.count(v))ans=max(ans,i-q[v]);
            else q[v]=i;
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    python 冒泡、二分查找
    pycharm 中按照文档引包方式,引包错误
    开发环境配置
    css,响应鼠标事件,文字变色
    Python 文档学习
    timestamp与timedelta,管理信息系统概念与基础
    中文词频统计
    文件方式实现完整的英文词频统计实例
    组合数据类型练习,英文词频统计实例上
    凯撒密码、GDP格式化输出、99乘法表
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7601968.html
Copyright © 2011-2022 走看看