二维前缀和。

二维前缀和就是求一个矩形内指定矩形区域中的和。

利用简单的容斥原理可以很容易的推导出来。

代码如下:

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_40799464/article/details/81532018