zoukankan      html  css  js  c++  java
  • 算法基础——前缀和及差分

    一、前缀和——基本就是公式(容斥原理)

     
     

     一维前缀和数组

    将S0定义成0是为了边界处理,统一形式。比如求 [1,10]的前缀和,其实就是S10,但是当我们定义S0 = 0后,我们就依然可以表示为 S10 - S0
    #include<iostream>
    using namespace std;
    const int N  = 100010;
    int n,m;
    int a[N],b[N];  //原数组和前缀和数组
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
        //前缀和数组
        for(int i = 1;i <= n;i ++) b[i] = b[i-1] + a[i];
        while(m--){
            int l,r;
            scanf("%d%d",&l,&r);
            cout<<b[r] - b[l-1]<<endl;
        }
    }
     

    二维前缀和矩阵

    前缀和问题一般是从1开始
    #include<iostream>
    using namespace std;
    
    const int N = 1010;
    int n,m,q;
    int a[N][N],b[N][N];
    
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <=m;j++)
                scanf("%d",&a[i][j]);
        
        //前缀和数组
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                b[i][j] =  b[i-1][j] + b[i][j-1] - b[i-1][j-1] + a[i][j];
        while(q--){
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            cout<<b[x2][y2] - b[x2][y1 -1] - b[x1 -1][y2] + b[x1-1][y1-1]<<endl;
        }
                
        // for(int i =1;i <= n;i++){
        //     for(int j = 1;j <= m;j++)
        //         printf("%d ",b[i][j]);
        //         puts("");
        // }    
         return 0;   
    }
     

      

     

    二、差分

    一维差分

    其实 a[i] 就是差分数组b[1]...b[ i ][的前缀和
    下面使构造方式,简单一看(不用管)
     
    #include<iostream>
    using namespace std;
    
    const int N = 100010;
    int n,m;
    int a[N],b[N];  //y原数组和差分数组
    
    //指定区间[l,r]加c,只需要使b[l] +c ,b[r+1] -c即可
    void insert(int l,int r,int c){
        b[l] += c;
        b[r+1] -= c;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        
        for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 
        
        for(int i = 1;i <= n;i++) insert(i,i,a[i]);  //做原数组的差分数组
        
        while(m--){
            int l,r,c;
            scanf("%d%d%d",&l,&r,&c);
            insert(l,r,c);
        }
        
        for(int i = 1;i <= n;i ++) b[i] += b[i-1];   //求前缀和
        for(int i = 1;i <= n;i ++) printf("%d ",b[i]);
        
        return 0;
    }
    开始时不需要考虑如何构造,将其看为0,然后再插一遍就可以了
     
     

    二维差分矩阵

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    其中 b[i][j]是提前假定好的,性质就是构造b,使得h二维数组a是二维数组b的前缀和
     
    #include<iostream>
    using namespace std;
    
    const int N = 1010;
    int n,m,q;
    
    int a[N][N],b[N][N];  //存放原矩阵和差分矩阵
    
    void insert(int x1,int y1,int x2,int y2,int c){
        b[x1][y1] += c;
        b[x1][y2+1] -= c;
        b[x2+1][y1] -= c;
        b[x2+1][y2+1] += c;
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                scanf("%d",&a[i][j]);
                
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                insert(i,j,i,j,a[i][j]);
                
        while(q--){
            int x1,y1,x2,y2,c;
            cin>>x1>>y1>>x2>>y2>>c;
            insert(x1,y1,x2,y2,c);
        }
        
        //求前缀和
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= m;j++){
                b[i][j] += b[i-1][j] + b[i][j-1] -b[i-1][j-1];
                printf("%d ",b[i][j]);
            }   
            cout<<endl;
        }
        
        return 0;
    }

     感谢y总!

  • 相关阅读:
    C#-WebForm-★★★JQuery-动画★★★
    C#-WebForm-★★★JQuery知识——DOM操作★★★
    C#-WebForm-★★★JQuery知识——基础知识、选择器、事件★★★
    C#-WebForm-组合查询(Queryable延迟查询、Intersect交集)、分页展示基础
    C#-WebForm-★★★LinQ-数据的条件组合查询并进行分页展示(未加各种限定)★★★
    C#-WebForm-光棒效果
    C#-WebForm-LinQ-条件精确查询、高级查询
    C#-WebForm-LinQ(一)-LinQ:语言集成查询(Language Integrated Query)-增删改查、属性扩展
    C#-WebForm JS定时器
    ★★★正则表达式★★★
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/12155700.html
Copyright © 2011-2022 走看看