二维前缀和,就是前缀和算法的二维形式,其基本思想与前缀和算法类似。
我们记 表示二维数组 的二维前缀和,则
让我们考虑如何在
的时间复杂度内求出
数组。
如图,
(自行配图理解)。
至于,如何求 的和,大家自行画图想想。
所谓的二阶差分,就是差分后再差分的意思。它的计算很简单,就是先差分一次,在对差分数组再差分一次。
重点在于如何利用二阶差分数组还原原数组。其实也很简单,就是两次前缀和即可。第一次前缀和求出差分数组,再一次前缀和就求出了原数组。
给你一个矩阵,里面有些点,让你横向切一刀,纵向切一刀,使得得到的四个区域内的最大的点数最少。
先对点的坐标离散化,然后直接用二维前缀和即可。
struct node{
int x,y,nx,ny,sub;
// x,y:输入时的坐标
// nx,ny:离散化后的坐标
void read_itself(int i){
scanf("%d%d",&x,&y);
sub=i;nx=ny=0;
}
}a[1100];int n,ans;
int sum[1100][1100];
inline bool cmp1(node a,node b){
return a.x<b.x;
}
inline bool cmp2(node a,node b){
return a.y<b.y;
}
inline bool cmp3(node a,node b){
return a.sub<b.sub;
}//按不同的关键字对a数组排序
int main(){
freopen("t1.in","r",stdin);
scanf("%d",&n);ans=0x3f3f3f3f;
for(int i=1;i<=n;i++)
a[i].read_itself(i);
sort(a+1,a+n+1,cmp1);
a[1].nx=1;//注意离散化的初始化
for(int i=2;i<=n;i++)
if (a[i].x==a[i-1].x)
a[i].nx=a[i-1].nx;
else a[i].nx=a[i-1].nx+1;
sort(a+1,a+n+1,cmp2);
a[1].ny=1;//注意离散化的初始化
for(int i=2;i<=n;i++)
if (a[i].y==a[i-1].y)
a[i].ny=a[i-1].ny;
else a[i].ny=a[i-1].ny+1;
sort(a+1,a+n+1,cmp3);
for(int i=1;i<=n;i++)
sum[a[i].nx][a[i].ny]++;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans=min(ans,max(max(sum[i][j],sum[i][n]-sum[i][j]),max(sum[n][j]-sum[i][j],sum[n][n]-sum[i][n]-sum[n][j]+sum[i][j])));
printf("%d",ans);
return 0;
}
二阶差分的模板题。
做二阶差分的题,只需把表格列出来,一个一个分析即可。这里为了节约篇幅,不给出表格。
const int N=3e6+100;
#define ll long long
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
ll d[N],p[N],t[N],n,m;
void write(ll a,bool b){
if (a<0){
putchar('-');
write(-a,false);
}
else if (a==0){
if (b) putchar('0');
}
else{
write(a/10,false);
putchar(a%10+'0');
}
}
void print(ll a){
write(a,true);
putchar(' ');
}
const int P=30000;
int main(){
m=read();n=read();
for(int i=1;i<=m;i++){
register int a,b;
b=read();a=read();
d[a-3*b+1+P]++;
d[a-2*b+1+P]-=2;
d[a+1+P]+=2;
d[a+2*b+1+P]-=2;
d[a+3*b+1+P]++;
}
for(int i=1;i<=n+P;i++)
p[i]=p[i-1]+d[i];
for(int i=1;i<=n+P;i++)
t[i]=t[i-1]+p[i];
for(int i=P+1;i<=n+P;i++)
print(t[i]);
return 0;
}