zoukankan      html  css  js  c++  java
  • 前缀和

    一维前缀和

    • 作用:快速查询数组a[l]~a[r]的和,时间复杂度为o(1)。
    • 求法:例如数组a[],用一个数组sum[]来记录它的前n项和,例如sum[n]表示a[1]+a[2]+...+a[n]。
    •  1 int sum[1000];
       2 void init()
       3 {
       4     for(int i=1; i<=n; i++)
       5         sum[i]=sum[i-1]+a[i];
       6 }
       7 int query(int l, int r)
       8 {
       9     return sum[r]-sum[l-1]; 
      10 }

    加一道前缀和的骚题。。。

    这道题居然可以用前缀和来解决,没想到。。。

    我们可以枚举自然数段的长度为i

    当i为2时,有 12 23 45 67

    为i3时有123 234 345 456

    为i4时有1234 2345 3456 4567

    我们可以发现这些串就可以表示任意一段的区间的和了, 然后奇妙的事发生了, 当要表示长度为i的区间的和时只需要用到第一列的数据和,然后在它的基础上加上k倍的i即可表示

    即设前缀和为a[n], 设要表示的数据和为n,如果存在一个区间和能表示这个数, 那么对应存在一个k满足n=sum[i]+k*i;然后上代码。

     1 #include<cstdio>
     2 long long a[2000005];
     3 int main()
     4 {
     5     int n;
     6     scanf("%d", &n);
     7     for(int i=1; i<=2000000; i++)
     8     {
     9         a[i]=a[i-1]+i;
    10     }
    11     for(int i=2000000; i>=2; i--)
    12     {
    13         if(n>=a[i] && (n-a[i])%i==0)
    14         {
    15             printf("%d %d
    ", 1+(n-a[i])/i, (n-a[i])/i+i);
    16         }
    17     }
    18 }

    二维前缀和

    • 作用:快速查询数组a[][]任意二维区间的和
    • 求法:用一个数组sum[n][m]表示所有a[n'][m']的和(1<=n'<=n,1<=m'<=m)。
    • 下面代码的例图。
    •  1 int sum[1000][1000];
       2 void init()
       3 {
       4     for(int i=1; i<=n; i++)
       5         for(int j=1; j<=m; j++)
       6             sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j];
       7 }
       8 int query(int x1, int y1, int x2, int y2)
       9 {
      10     return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
      11 }

     一维差分

    • 作用:设数组为a[],对多次a数组上的区间[l,r]实现加减val的操作(将对区间的的操作转化为对两个端点的操作)。
    • 做法:
       1 int a[n];
       2 int d[n];
       3 int c[n];
       4 void init(int l, int r, int val)
       5 {
       6     d[l]+=val;d[r+1]-=val;
       7 }
       8 for(int    i=1; i<=n; i++)
       9 {
      10     c[i]=c[i-1]+d[i];
      11 }
      12 for(int i=1; i<=n; i++)
      13 {
      14     a[i]+=c[i];
      15 }

    二维差分

    •  1 void init(int x1, int y1, int x2, int y2, int val)
       2 {
       3     sum[x1][y1] += val;
       4     sum[x1][y2 + 1] -= val;
       5     sum[x2 + 1][y1] -= val;
       6     sum[x2 + 1][y2 + 1] += val;
       7 }
       8 
       9 void get()
      10 {
      11     for(int i = 1; i <= n; i++)
      12         for(int j = 1; j <= n; j++)
      13             sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];
      14 }
  • 相关阅读:
    JDBC遇到向ORACLE数据库表执行插入操作时,报错“列在此处不允许”
    关于对称加密和非对称加密以及签名,认证和证书的理解
    .net framework 各版本区别
    数据库设计三大范式
    业务系统设计
    修改 Windows 服务器默认远程端口3389
    iis读取不到本地证书问题 提示已经导入成功
    HTTPS 建立连接的详细过程
    使用ServiceStack构建Web服务
    转-微信支付(公众号支付JSAPI)
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/9371254.html
Copyright © 2011-2022 走看看