用单调栈的话不严格的O(n^3)可以轻松艹过去,统计的时候要差分。
可以发现,对于一个单调栈里的元素,从它进栈到出栈都会重复类似的计算。。再差分一波后就可以只在出栈的时候计算一下了。
具体的话看代码吧。。
O(n^3):
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define ll long long 7 #define ui unsigned int 8 #define ull unsigned long long 9 using namespace std; 10 const int maxn=606; 11 char s[maxn]; 12 int h[maxn],st[maxn],l[maxn]; 13 int an[maxn][maxn]; 14 int i,j,k,n,m; 15 16 int ra,fh;char rx; 17 inline int read(){ 18 rx=getchar(),ra=0,fh=1; 19 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 20 if(rx=='-')fh=-1,rx=getchar(); 21 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 22 } 23 inline void add(int y1,int x2,int y2){ 24 // printf("add:1,%d %d,%d ",y1,x2,y2); 25 an[x2][y2]++,an[x2][y1-1]--; 26 } 27 inline void addall(int len,int st2,int h){ 28 for(register int i=1;i<=len;i++)an[h][i+st2]++,an[h][i-1]--; 29 // add(i,h,i+st2); 30 // an[h][1+st2]++,an[h][len+st2+1]--, 31 // an[h][0]--,an[h][len]++; 32 } 33 34 char ss[10];int len; 35 inline void outx(int x){ 36 if(!x){putchar('0');return;} 37 while(x)ss[len++]=x%10,x/=10; 38 while(len)putchar(ss[--len]+48); 39 } 40 int main(){ 41 n=read(),m=read();//register int k; 42 for(i=1;i<=n;i++){ 43 scanf("%s",s+1); 44 int top=0; 45 for(j=1;j<=m+1;j++){ 46 h[j]=s[j]=='1'?h[j]+1:0; 47 while(top&&h[st[top]]>=h[j])addall(j-st[top],st[top]-l[top],h[st[top]]),top--; 48 st[++top]=j,l[top]=st[top-1]+1; 49 //for(k=1;k<=top;k++)add(j-st[k]+1,h[st[k]],j-l[k]+1); 50 } 51 } 52 // for(i=1;i<=n;i++)for(j=1;j<=m;j++)an[i][j]+=an[i][j-1]; 53 // for(i=1;i<=n;printf("%d ",an[i][m]),i++)for(j=1;j<m;j++)printf("%d ",an[i][j]); 54 for(i=n;i;i--)for(j=m;j;j--)an[i][j]+=an[i+1][j]+an[i][j+1]-an[i+1][j+1]; 55 for(i=1;i<=n;outx(an[i][m]),putchar(' '),i++)for(j=1;j<m;j++)outx(an[i][j]),putchar(' '); 56 }
O(n^2):
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define ll long long 7 #define ui unsigned int 8 #define ull unsigned long long 9 using namespace std; 10 const int maxn=606; 11 char s[maxn]; 12 int h[maxn],st[maxn],l[maxn]; 13 int an[maxn][maxn]; 14 int i,j,k,n,m; 15 16 int ra,fh;char rx; 17 inline int read(){ 18 rx=getchar(),ra=0,fh=1; 19 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 20 if(rx=='-')fh=-1,rx=getchar(); 21 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 22 } 23 24 inline void addall(int len,int st2,int h){ 25 an[h][1+st2]++,an[h][len+st2+1]--, 26 an[h][0]--,an[h][len]++; 27 } 28 29 char ss[10];int len; 30 inline void outx(int x){ 31 if(!x){putchar('0');return;} 32 while(x)ss[len++]=x%10,x/=10; 33 while(len)putchar(ss[--len]+48); 34 } 35 int main(){ 36 n=read(),m=read();register int i,j; 37 for(i=1;i<=n;i++){ 38 scanf("%s",s+1); 39 int top=0; 40 for(j=1;j<=m+1;j++){ 41 h[j]=s[j]=='1'?h[j]+1:0; 42 while(top&&h[st[top]]>=h[j])addall(j-st[top],st[top]-l[top],h[st[top]]),top--; 43 st[++top]=j,l[top]=st[top-1]+1; 44 } 45 } 46 for(i=1;i<=n;i++)for(j=1;j<=m;j++)an[i][j]+=an[i][j-1]; 47 for(i=1;i<=n;i++)an[i][m+1]=0;for(i=1;i<=m;i++)an[n+1][i]=0; 48 for(i=n;i;i--)for(j=m;j;j--)an[i][j]+=an[i+1][j]+an[i][j+1]-an[i+1][j+1]; 49 for(i=1;i<=n;outx(an[i][m]),putchar(' '),i++)for(j=1;j<m;j++)outx(an[i][j]),putchar(' '); 50 }