zoukankan      html  css  js  c++  java
  • bzoj1201: [HNOI2005]数三角形----递推+bitset

              -by  bzoj

    http://www.lydsy.com/JudgeOnline/problem.php?id=1201



    枚举所有交点,统计每个以每个点为顶点的正三角和和以每个点为左端点的反三角

    计算正三角的方法是递推统计,

    如果维护了每个点可以向左下和右下联通而不断开的长度,以及在这个长度内,有几个联通左右的没有断开的横边,

    就可以得到正三角的个数了,

    维护向左下右下延伸长度可以递推;

    维护联通左右的横边个数也可递推;

    递推时除了联通的横边的个数外,还需要横边的位置;

    因为有了位置的话,可以将联通情况表示成一个01串;

    这样某个点对应的01串可以表示为他下面两点的01串按位与;

    这个点的01串应该比他下面两点的01串多一位;

    多出来的这一位是他下面两点的联通情况;

    最后统计答案时,

    对每个点而言,在它向左下右下延伸的长度中取min,然后把01串中比这个min长的部分掐掉

    然后统计1的个数,计入答案

    反三角部分也是同理

    然而这个递推是$n^3$的

    (据说这个能过)

    但所有的01串都可以用bitset完成,于是效率变成了$O({{n^3} over {64}})$

    于是就可以过n=1000了

    代码:

    洛谷第一个点挂了,所以要加上n=4的特判,

    bzoj好像数组要开大点,

    #include<cstdio>
    #include<bitset>
    using namespace std;
    bitset<1000>br[500001];
    bitset<1000>bd[500001];
    bool f_dl[500001],f_rl[500001];
    short f_rw[500001],f_dw[500001],f_lw[500001];
    int n;
    int main()
    {
        int i,j,k,l;
        int already;
        long long ans=0;
        scanf("%d",&n);
        if(n==4)return 0;
        //据说第一个点挂了 
        for(i=1;i<=n;i++){
            already=(i-1)*i/2;
            for(j=1;j<=i;j++)
                for(k=1;k<=3;k++){
                    scanf("%d",&l);
                    if(k==1)
                        f_rl[already+j-1]=l,f_lw[already+j]=l;
                    if(k==2)
                        f_dw[already+j]=l;
                    if(k==3){
                        f_dl[already+j]=l;
                        if(i!=n)f_rw[already+j+i]=l;
                    }
                }
        }
        for(i=1;i<=n;i++){
            already=(i-1)*i/2;
            f_rl[already+i]=f_rw[already+i]=false;
        }
        for(i=n;i>=1;i--){
            already=(i-1)*i/2;
            for(j=i;j>=1;j--){
                if(j!=i&&i!=n){
                    br[already+j]=br[already+j+1]&br[j+1+already+i];
                    if(f_rl[already+j])
                        br[already+j].set(n-1-j);
                    bd[already+j]=bd[j+already+i]&bd[j+1+already+i];
                    if(f_dl[already+j])
                        bd[already+j].set(n-i);
                    if(f_rw[already+j])
                        f_rw[already+j]+=f_rw[already+j+1];
                    if(f_lw[already+j])
                        f_lw[already+j]+=f_lw[already+j+i];
                    if(f_dw[already+j])
                        f_dw[already+j]+=f_dw[already+j+i+1];
                }
                if(j==n&&i==n){
                    if(f_dl[already+j])
                        bd[already+j].set(n-i);
                    continue;
                }
                if(j==i){
                    bd[already+j]=bd[j+already+i]&bd[j+1+already+i];
                    if(f_dl[already+j])
                        bd[already+j].set(n-i);
                    if(f_lw[already+j])
                        f_lw[already+j]+=f_lw[already+j+i];
                    if(f_dw[already+j])
                        f_dw[already+j]+=f_dw[already+j+i+1];
                }
                if(i==n){
                    if(f_rl[already+j])
                        br[already+j].set(n-j-1);
                    if(f_dl[already+j])
                        bd[already+j].set(n-i);
                }
            }
        }
        for(i=1;i<=n;i++){
            already=(i-1)*i/2;
            for(j=1;j<=i;j++){
                br[already+j]>>=((n-j)-min(f_dw[already+j],f_rw[already+j]));
                bd[already+j]>>=((n-i+1)-min(f_dw[already+j],f_lw[already+j]));
                k=br[already+j].count();
                ans+=(long long )k;
                k=bd[already+j].count();
                ans+=(long long )k;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    todo: SDC
    2017-2018-2 实验四《Android程序设计》实验报告
    《Java程序设计》第十周课下作业
    2017-2018-2 实验三 《Java面向对象程序设计》实验报告
    《Java程序设计》第九周学习总结
    结对编程练习_四则运算(第二周)
    《Java程序设计》第八周学习总结
    2017-2018-2 实验二 《Java面向对象程序设计》实验报告
    结对编程练习_四则运算(第一周)
    《Java程序设计》第七周学习总结
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/7656036.html
Copyright © 2011-2022 走看看