题解 SP16180 【RATAR - Ratar】

hicc0305

2018-10-04 15:15:58

Solution

枚举两个矩形的连接点,然后统计出左上的所有矩形的面积,用f[i]存面积为i的矩形有多少个。然后统计右下的所有矩形的面积的时候,每算出一个矩形面积j,答案就加上f[j]。然后左下和右上同理。 注意:清空时千万不要用memset,会超时的,然后我一开始是用map的,因为STL的劣根性,会T。。是的不管是用clear()还是一个一个删都会T的!但理论时间复杂度上$n^4*log_2n$是过得去的!! 那么代码: ``` #include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #pragma GCC optimize (2) #define int long long #define it int using namespace std; const int Max=2500*1000; inline int read() { int X=0,w=0; char c=0; while(c<'0'||c>'9') {w|=c=='-';c=getchar();} while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar(); return w?-X:X; } int n,ans=0; int a[60][60],b[60][60]; int sum[60][60]; it f[Max*2]; int get(int x1,int y1,int x2,int y2) { if(x1>x2) swap(x1,x2); if(y1>y2) swap(y1,y2); return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; } signed main() { n=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) b[i][j]=b[i][j-1]+a[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) sum[i][j]=sum[i-1][j]+b[i][j]; for(int a=1;a<=n;a++) for(int b=1;b<=n;b++) { for(int c=a+1;c<=n;c++) for(int d=b+1;d<=n;d++) f[get(a+1,b+1,c,d)+Max]++; for(int c=1;c<=a;c++) for(int d=1;d<=b;d++) ans+=f[get(a,b,c,d)+Max]; for(int c=a+1;c<=n;c++) for(int d=b+1;d<=n;d++) f[get(a+1,b+1,c,d)+Max]--; for(int c=1;c<=a;c++) for(int d=b+1;d<=n;d++) f[get(a,b+1,c,d)+Max]++; for(int c=a+1;c<=n;c++) for(int d=1;d<=b;d++) ans+=f[get(a+1,b,c,d)+Max]; for(int c=1;c<=a;c++) for(int d=b+1;d<=n;d++) f[get(a,b+1,c,d)+Max]--; } printf("%lld",ans); return 0; } ```