Editorial for Đếm hình chữ nhật trên bảng 0-1
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của flashmt
const fi=''; fo=''; maxn=1010; var n,m:longint; re:int64; f,st:array[0..maxn] of longint; num:array[0..maxn] of int64; procedure pr; var i,j,now,t:longint; c:char; begin assign(input,fi); reset(input); readln(m,n); re:=0; fillchar(f,sizeof(f),0); for i:=1 to m do begin for j:=1 to n do begin read(c); if c='0' then f[j]:=0 else inc(f[j]); end; readln; num[0]:=0; f[0]:=-1; st[0]:=0; now:=0; for j:=1 to n do begin while f[st[now]]>=f[j] do dec(now); t:=st[now]; inc(now); st[now]:=j; num[j]:=f[j]*(j-t)+num[t]; re:=re+num[j]; end; end; close(input); end; procedure wf; begin assign(output,fo); rewrite(output); write(re); close(output); end; begin pr; wf; end.
Code mẫu của happyboy99x
#include<cstdio> const int N = 1005; /* Stack */ int stack[N], topS; void init() { topS = 0; } int top() { return stack[topS-1]; } int pop() { return stack[--topS]; } void push(const int &x) { stack[topS++] = x; } /* End of Stack */ int m, n, f[N][N], left[N]; long long dp[N]; char a[N][N]; /* f[y][x] = k <=> a[y..y+k-1][x] = 11..., k max */ void enter() { scanf("%d%d",&m,&n); for(int i = 0; i < m; ++i) scanf("%s", a[i]); } void calcF() { for(int j = 0; j < n; ++j) for(int i = m-1; i >= 0; --i) f[i][j] = a[i][j] == 0x31 ? f[i+1][j] + 1 : 0; } void solve() { long long res = 0; for(int i = 0; i < m; ++i) { left[0] = 0; init(); for(int j = 1; j < n; ++j) if(f[i][j] > f[i][j-1]) left[j] = j, push(j-1); else { while(topS && f[i][j] <= f[i][top()]) pop(); left[j] = topS ? top() + 1 : 0; } for(int j = 0; j < n; ++j) res += dp[j] = (left[j] == 0 ? 0 : dp[left[j]-1]) + (j - left[j] + 1) * f[i][j]; } printf("%lld\n", res); } int main() { enter(); calcF(); solve(); return 0; }
Code mẫu của ladpro98
#include <iostream> using namespace std; const int N = 1010; char a[N]; int c[N][N]; int h[N]; int s[N]; int size; int n, m; int main() { cin >> m >> n; for (int i = 1; i <= m; ++i) { cin >> (a + 1); for (int j = 1; j <= n; ++j) h[j] = a[j] == '1' ? h[j] + 1 : 0; size = 0; for (int j = 0; j <= n + 1; ++j) { while (size && h[s[size]] >= h[j]) { int w = j - 1 - s[size - 1]; ++c[max(h[s[size - 1]], h[j]) + 1][w]; --c[h[s[size]] + 1][w]; --size; } s[++size] = j; } } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) c[i + 1][j] += c[i][j]; int cur = 0; for (int j = n; j >= 1; --j) { cur += c[i][j]; c[i][j] = c[i][j + 1] + cur; } } long long ans = 0; for (int i = 1; i <= m; ++i) for (int j = 1; j <= n; ++j) ans += c[i][j]; cout << ans << endl; }
Code mẫu của RR
//Written by RR {$IFDEF RR} {$R+,Q+,S+} {$inline off} {$Mode objFPC} {$ELSE} {$R-,Q-} {$inline on} {$Mode objFPC} {$ENDIF} uses math; const FINP = {$IFDEF RR} 'input.txt'; {$ELSE} ''; {$ENDIF} FOUT = {$IFDEF RR} 'output.txt'; {$ELSE} ''; {$ENDIF} MAXN = 1111; var f1,f2 : text; m,n : longint; a : array[1..MAXN,1..MAXN] of byte; h,stack : array[0..MAXN] of longint; left,right : array[0..MAXN] of longint; ok : array[0..MAXN] of boolean; procedure openF; begin assign(f1,FINP); reset(f1); assign(f2,FOUT); rewrite(f2); end; procedure closeF; begin close(f1); close(f2); end; procedure inp; var i,j:longint; ch:char; begin readln(f1,m,n); for i:=1 to m do begin for j:=1 to n do begin read(f1,ch); if ch='0' then a[i,j]:=0 else a[i,j]:=1; end; readln(f1); end; end; procedure solve; var count:int64; i,j,k:longint; l,r:longint; top:longint; begin count:=0; for i:=1 to m do begin for j:=1 to n do if a[i,j]=1 then inc(h[j]) else h[j]:=0; top:=0; stack[0]:=0; for j:=1 to n do begin while (top>0) and (h[stack[top]]>=h[j]) do dec(top); left[j]:=stack[top]+1; inc(top); stack[top]:=j; end; top:=0; stack[0]:=n+1; for j:=n downto 1 do begin while (top>0) and (h[stack[top]]>=h[j]) do dec(top); right[j]:=stack[top]-1; inc(top); stack[top]:=j; end; top:=0; stack[0]:=0; for j:=1 to n do begin while (top>0) and (h[stack[top]]>h[j]) do dec(top); if h[stack[top]]=h[j] then ok[j]:=false else ok[j]:=true; inc(top); stack[top]:=j; end; {$IFDEF RR} writeln(f2); writeln(f2,'============='); writeln(f2,'Hang ',i); for j:=1 to n do write(f2,h[j],' '); writeln(f2); writeln(f2,'left: '); for j:=1 to n do write(f2,left[j],' '); writeln(f2); writeln(f2,'right: '); for j:=1 to n do write(f2,right[j],' '); writeln(f2); writeln(f2,'ok: '); for j:=1 to n do if ok[j] then write(f2,'1 ') else write(f2,'0 '); writeln(f2); writeln(f2,'============'); writeln(f2); {$ELSE} {$ENDIF} for j:=1 to n do if ok[j] then begin l:=left[j]; r:=right[j]; k:=max(h[l-1],h[r+1]); inc(count,(r-l+1)*(r-l+2)*(h[j]-k)>>1); {$IFDEF RR} writeln(f2,' cot ',j); writeln(f2,' left = ',l,' right = ',r,' count+= ',(r-l+1)*(r-l+2)*(h[j]-k)>>1); {$ELSE} {$ENDIF} end; end; writeln(f2,count); end; begin openF; inp; solve; closeF; end.
Code mẫu của hieult
#include <cstdio> #include <cstring> //#include <conio.h> int m,n,chay, h[1002],s[1002]; long long KQ, soh[1002]; char a[1002]; int main() { //freopen("CREC01.in","r",stdin); scanf("%d %d",&m,&n); gets(a); for(int i = 1;i<=m;i++) { gets(a); for(int j = 1;j<=n;j++) { if(a[j-1]=='0') h[j]=0; else h[j]++; } int chay = 0;s[0] = 0; soh [0] = 0; h[0] = -1; for(int j = 1;j<=n;j++) { while(h[s[chay]]>=h[j]) chay--; int flag = s[chay]; s[++chay] = j; soh[j] = h[j]*(j-flag) + soh[flag]; KQ = KQ+soh[j]; } } printf("%lld",KQ); //getch(); }
Code mẫu của ll931110
#include <iostream> #include <cstring> #define MAXN 1001 int stack[MAXN],h[MAXN],m,n; long long res,calc[MAXN]; char s[MAXN]; int main() { int i,j,top,tmp; //freopen("crec01.inp","r",stdin); //freopen("crec01.out","w",stdout); scanf("%d%d", &m, &n); res = 0; gets(s); h[0] = -1; for (i = 1; i <= m; i++) { gets(s); for (j = 1; j <= n; j++) if (s[j - 1] == '1') h[j]++; else h[j] = 0; top = 0; for (j = 1; j <= n; j++) { while (h[stack[top]] >= h[j]) top--; tmp = stack[top]; calc[j] = (j - tmp) * h[j] + calc[tmp]; res += calc[j]; top++; stack[top] = j; } } printf("%lld", res); }
Code mẫu của skyvn97
#include<cstdio> #include<stack> #define MAX 1010 #define FOR(i,a,b) for (int i=(a);i<=(b);i=i+1) #define REP(i,n) for (int i=0;i<(n);i=i+1) using namespace std; char a[MAX][MAX]; int h[MAX][MAX]; int l[MAX]; int c[MAX][MAX]; int m,n; stack<int> st; void init(void) { scanf("%d",&m); scanf("%d",&n); FOR(i,1,m) { scanf("%s",a[i]+1); FOR(j,1,n) { if (a[i][j]=='1') h[i][j]=h[i-1][j]+1; else h[i][j]=0; } } } void count(void) { FOR(i,1,m) { while (!st.empty()) st.pop(); l[1]=1; c[i][1]=h[i][1]; FOR(j,2,n) { if (h[i][j]>h[i][j-1]) { l[j]=j; st.push(j-1); } else { while (!st.empty() && h[i][st.top()]>=h[i][j]) st.pop(); if (st.empty()) l[j]=1; else l[j]=st.top()+1; } c[i][j]=c[i][l[j]-1]+h[i][j]*(j-l[j]+1); } } long long res=0; FOR(i,1,m) FOR(j,1,n) res+=c[i][j]; printf("%lld",res); } int main(void) { init(); count(); return 0; }
Code mẫu của khuc_tuan
//{$APPTYPE CONSOLE} {$MODE DELPHI} var m, n, i, j, t : integer; a : array[0..1001] of char; h, l, c : array[0..1001] of integer; r : int64; begin readln(m,n); r := 0; for i:=1 to m do begin readln(a); for j:=0 to n-1 do begin if a[j]='0' then h[j] := 0 else inc(h[j]); t := j-1; while (t >= 0) and (h[t] >= h[j]) do t := l[t]; l[j] := t; c[j] := (j-t) * h[j]; if t >= 0 then c[j] := c[j] + c[t]; r := r + c[j]; end; end; writeln(r); end.
Comments