二维前缀和就是求一个矩形内指定矩形区域中的和。
利用简单的容斥原理可以很容易的推导出来。
代码如下:
#include <iostream> //简单的容斥原理。
using namespace std; //二维前缀和。
const int inf=105;
int a[inf][inf];
int jx[inf][inf];
int main()
{
int n;
cout<<"请输入行数;"<<endl;
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
//进行预处理fx数组。
for(int i=2;i<=n+1;i++)
for(int j=2;j<=n+1;j++) //使用容斥原理。
{
jx[i][j]=a[i-1][j-1]+jx[i][j-1]+jx[i-1][j]-jx[i-1][j-1];
}
int u,v,x,y; //代表的是(u,v)和(x,y)之间的矩阵和。
cout<<"请输入所要求和矩形的左上角和右下角的坐标"<<endl;
while(cin>>u>>v>>x>>y)
{
int ans=jx[x][y]-jx[u+1][y]-jx[x][v+1]+jx[u+1][v+1]; //容斥原理。
cout<<ans<<endl;
}
return 0;
}
使用二维前缀和的一道题
百度之星资格赛 字串查询:
http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=820&pid=1002
(题意一大串,其实就是要你求给定的区间中的最小字母的个数。利用二维前缀和可以保证在O(n)时间内求得。)
代码如下:
#include <iostream>
#include <cstring>
using namespace std;
const int inf=1e5+10;
int arr[inf][28];
int ans[inf][28];
int main()
{
int N;
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
int n,p;
scanf("%d %d",&n,&p);
memset(arr,0,sizeof(arr));
getchar();
for(int j=1;j<=n;j++)
{
char temp;
scanf("%c",&temp);
arr[j][temp-64]++;
}
for(int p=1;p<=n;p++)
{
for(int q=1;q<=26;q++)
{
ans[p][q]=arr[p][q]+ans[p-1][q]+ans[p][q-1]-ans[p-1][q-1];
}
}
printf("Case #%d:\n",i);
for(int j=1;j<=p;j++)
{
int l,r;
scanf("%d %d",&l,&r);
int x=0,y=2; //(l-1,x)到(r+1,y);
int flag;
while( (flag=ans[l-1][x]+ans[r][y-1]-ans[l-1][(y++)-1]-ans[r][x++])==0 ){}
printf("%d\n",flag);
}
}
return 0;
}