B——蜜汁做法
Description
思路
对于一个矩阵,
左上角为[x1,y1],右下角为[x2,y2]
它的权值计算为
ax1*(by1+…+by2) +
…
ax2*(by1+…+by2)
即(ax1+…+ax2)*(by1+…+by2)
发现x跟y没有必然的关系
可以分开处理
枚举a的可能区间[x1,x2],预处理所有的by区间和
对于一个限制[L,R]
若x选定为[x1,x2],则(L/suma[x1,x2],R/suma[x1,x2])
为by区间和可以选择的范围(注意考虑小数取整)
对于这个范围我就可以在预处理的by区间在排序后进行二分,找到符合的区间个数
时间复杂度O(n2log2(m2))
(ctl+c,ctl+v的教练的题解QAQ。没办法,写得太好了)
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2*1e3;
ll n,m,l,r,cnt,ans,a[N],b[N],s[N*N],sum;
int main()
{
scanf("%lld%lld%lld%lld",&n,&m,&l,&r);
//前缀和维护a,b数组的任意区间和
for(int i=1,k;i<=n;i++)
scanf("%d",&k),a[i]=a[i-1]+k;
for(int i=1,k;i<=m;i++)
scanf("%d",&k),b[i]=b[i-1]+k;
//预处理b数组的所有区间和并排序
for(int i=1;i<=m;i++)
for(int j=i;j<=m;j++)
s[++cnt]=b[j]-b[i-1];
sort(s+1,s+cnt+1);
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
sum=a[j]-a[i-1];//对于每个确定的a数组区间
ll p=l/sum,q=r/sum;//得到b数组区间和的上界、下界
if(l%sum) p++;
//在s数组中二分得到上、下界的位置
ll x=upper_bound(s+1,s+cnt+1,q)-s;
ll y=lower_bound(s+1,s+cnt+1,p)-s;
ans+=x-y;//累计满足上下界的答案
}
printf("%lld",ans);
return 0;
}
}