博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2727 双十字(树状数组)
阅读量:6902 次
发布时间:2019-06-27

本文共 1718 字,大约阅读时间需要 5 分钟。

题目链接:

题意:

 

思路:思路来自。首先对于每个位置(i,j)用C[i][j]表示该位置同时向左右能延伸的最大长度,用down[i][j]表示向下能延伸的最大长度(其实这里可以用一维的)。然后就是统计。我们一列一列枚举。对于每一列,一行一行来。每次到达一行,(i,k),若C[i][k]>0就可以统计答案了。若该行的上面有一行j(当然j<i-1了),C[j][k]>0,那么就要增加答案了。设k列最上的1的行为top。可知:

我们不管dowm[i][j]的话,可以得到三个参数:

因此我们只要开三个树状数组维护上面三个值就可以了。

 

i64 S1[N],S2[N],S3[N];
int d[N],n,m,K,L[N],R[N],C[N],down[N];
void up(i64 &x,i64 y)
{
    x=(x+y)%mod;
}
void add(i64 S[],int p,i64 x)
{
    while(p<=m) S[p]=(S[p]+x)%mod,p+=p&-p;
}
i64 get(i64 S[],int p)
{
    i64 ans=0;
    while(p>0) up(ans,S[p]),p-=p&-p;
    return ans;
}
int ID(int i,int j)
{
    return (i-1)*m+j;
}
void init()
{
    int i,j;
    FOR1(i,n)
    {
        L[ID(i,1)]=d[ID(i,1)]?-1:0;
        R[ID(i,m)]=d[ID(i,m)]?-1:0;
        for(j=2;j<=m;j++)
        {
            if(d[ID(i,j)]) L[ID(i,j)]=-1;
            else L[ID(i,j)]=L[ID(i,j-1)]+1;
        }
        for(j=m-1;j>=1;j--)
        {
            if(d[ID(i,j)]) R[ID(i,j)]=-1;
            else R[ID(i,j)]=R[ID(i,j+1)]+1;
        }
        FOR1(j,m) C[ID(i,j)]=min(L[ID(i,j)],R[ID(i,j)]);
    }
    FOR1(j,m) 
    {
        down[ID(n,j)]=d[ID(n,j)]?-1:0;
        for(i=n-1;i>=1;i--) 
        {
            if(d[ID(i,j)]) down[ID(i,j)]=-1;
            else down[ID(i,j)]=down[ID(i+1,j)]+1;
        }
    }
}
int top,pre;
void clear()
{
    top=pre=0;
    int i;
    for(i=0;i<=m;i++) S1[i]=S2[i]=S3[i]=0;
}
i64 ans;
void update(i64 x,int i,int j)
{
    i64 temp=get(S1,x)*x%mod-get(S2,x);
    temp+=x*(x-1)/2%mod*(get(S3,m)-get(S3,x))%mod;
    temp%=mod;
    ans=(ans+temp*down[ID(i,j)])%mod;
}
i64 S(i64 x) {return x*(x+1)/2%mod;}
void deal()
{
    int i,j,k,x;
    for(j=2;j<m;j++)
    {
        clear();
        for(i=1;i<n;i++)
        {
            if(d[ID(i,j)]) clear();
            else if(top==0) top=i;
            else 
            {
                if(C[ID(i,j)]>0) update(C[ID(i,j)],i,j);
                if(pre) 
                {
                    x=C[ID(i-1,j)];
                    add(S1,x,x*(i-1-top)%mod);
                    add(S2,x,S(x)*(i-1-top)%mod);
                    add(S3,x,i-1-top);
                    pre=0;
                }
                if(C[ID(i,j)]) pre=i;
            }
        }
    }
    PR(ans);
}
int main()
{
    RD(n,m,K);
    int i,x,y;
    FOR1(i,K) RD(x,y),d[ID(x,y)]=1;
    init();
    deal();
}

你可能感兴趣的文章
html之DOM总结
查看>>
java实现 排序算法(鸡尾酒排序&选择排序&插入排序&二分插入排序)
查看>>
c++ assert
查看>>
VS2017自动添加头部注释
查看>>
游戏动画中欧拉角与万向锁的理解
查看>>
Sorting It All Out(拓扑排序)
查看>>
python oop面向对象笔记
查看>>
python numpy模块使用笔记(更新)
查看>>
vue-cli构建项目 npm run build后应该怎么运行在本地查看效果
查看>>
unix平台下I/O聚集和分离的一种方案
查看>>
1081. Binary Lexicographic Sequence(找规律)
查看>>
Postman笔记 - 入门好文
查看>>
通过游戏来学习编程
查看>>
周记(飞船一号
查看>>
openssl初步使用
查看>>
Vue项目碰到"‘webpack-dev-server’不是内部或外部命令,也不是可运行的程序或批处理文件"报错...
查看>>
模拟任务资源管理器的小程序
查看>>
通过一个例子,总结下检测数组属性的N种方法
查看>>
Samba结合AD实现域帐号认证的文件服务器
查看>>
laravel的Eloquent中的get()和Query/Builder中的get()
查看>>