题目描述
数据说明:
输入
第一行依次给出n,m,L,R
第二行n个数表示数组a
第三行m个数表示数组b
输出
输出满足条件的子矩阵个数
输入样例
3 3 3 8
3 2 3
2 3 1
输出样例
10
题解:
其实矩阵 [ x1 , y1 ] [ x2 , y2 ] 的值为
ax1 * ( by1 + … + by2 ) +
…
ax2 * ( by1 + … + by2 )
即 ( ax1 + … + ax2 ) * ( by1 + … + by2 )
然后就会发现, x 和 y 并没有什么关系
则就可以先处理出 y 相加的每一种可能性,并排一下序
之后在枚举 a 的 x1 , x2 ,而 y 的区间和就可以用前缀和和二分来作
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath> //开longlong!!!
#define LL long long
#define ull unsigned LL
#define db double
#define ldb long db
#define re register
using namespace std;
const LL N=1e7+100,M=2020;
LL n,m,l,r,len,ans,now,a[N],b[N],s[N];
int main ( )
{
scanf ( "%lld %lld %lld %lld",&n,&m,&l,&r );
for ( re LL i=1;i<=n;i++ ) scanf ( "%lld",&a[i] ),a[i]+=a[i-1];
for ( re LL i=1;i<=m;i++ ) scanf ( "%lld",&b[i] ),b[i]+=b[i-1];
for ( int i=1;i<=m;i++ ) for ( int j=i;j<=m;j++ ) s[++len]=b[j]-b[i-1];
sort ( s+1,s+1+len );
for ( int i=1;i<=n;i++ )
{
for ( int j=i;j<=n;j++ )
{
now=a[j]-a[i-1];
LL wz_1=lower_bound ( s+1,s+1+len,ceil ( l*1.0/now ) )-s;
LL wz_2=upper_bound ( s+1,s+1+len,r*1.0/now )-s;
ans+=( wz_2-wz_1 );
}
}
printf ( "%lld",ans );
return 0;
}