BJ模拟:矩阵(单调队列)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35649707/article/details/79901558

传送门

题解:
好题啊。。

我们可以枚举起始行然后做单调队列。

注意直接计算贡献是n3的,不过我们可以加入元素时不计算贡献,在弹掉元素时只计算它和前面一个的贡献,剩下的贡献和后面的一起算,时间复杂度为O(n2)

#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;
typedef unsigned long long ULL;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}
inline void rd(char *c) {
    char ch=nc();
    while(isspace(ch)) ch=nc();
    while(!isspace(ch)) *c++=ch;
}
inline void W(int x) {
    static int buf[50];
    if(!x) {putchar('0'); return;}
    if(x<0) {putchar('-'); x=-x;}
    while(x) {buf[++buf[0]]=x%10; x/=10;}
    while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}

const int N=4e3+50;
int n,m,k,h[N],stk[N],p[N],tl;
int ch[N][N];
LL f[N][N],ans;
int main() {
    n=rd(), m=rd(), k=rd();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+(i*j>=k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            f[i][j]=f[i][j-1]+f[i][j];
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ch[i][j]=rd();
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++)
            h[j]=(ch[i][j]==0) ? (h[j]+1) : 0;
        tl=0;
        for(int j=1;j<=m;j++) {
            while(tl && h[stk[tl]]>=h[j]) {
                int dis=j-1-stk[tl-1];
                ans+=f[h[stk[tl]]][dis] - f[max(h[stk[tl-1]],h[j])][dis];
                --tl; 
            }
            stk[++tl]=j; 
        }
        while(tl) { 
            int dis=m-stk[tl-1];
            ans+=f[h[stk[tl]]][dis] - f[h[stk[tl-1]]][dis];
            --tl; 
        }
    }
    cout<<ans;
}
展开阅读全文

没有更多推荐了,返回首页