zoukankan      html  css  js  c++  java
  • 牛客暑假多校 H Prefix sum

    题意:

    现在有一个2维矩阵, 初始化为0。 并且这个矩阵是及时更新的。 dp[i][j] = dp[i-1][j] + dp[i][j-1];

    现在有2种操作:

    0 x y   dp[1][x] += y

    1 x  查询dp[k][x]的值。

    题解:

    神奇的分块算法。

    首先我们可以发现 如果在一个 x 的位置加上了值 y 那么 在 x' 的位置加上的值是 从 (1, x) 走到 (k,x')的方案数* y, 只能向下向右移动。

    现在我们有2种最暴力的做法:

    1 每次更新都暴力更新整个矩阵  然后o1得到结果

    2 每次都把添加的数存一下 然后询问的时候通过组合数去找到答案。

    这两种做法复杂度都很爆炸。

    但是 如果把这2种做法结合一下, 每次都把添加的值存起来,然后询问的时候通过组合数去找答案, 然后当存了的数大于一定的数目的时候再暴力更新整个矩阵。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
     4 #define LL long long
     5 #define ULL unsigned LL
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 #define lch tr[x].son[0]
    12 #define rch tr[x].son[1]
    13 #define max3(a,b,c) max(a,max(b,c))
    14 #define min3(a,b,c) min(a,min(b,c))
    15 typedef pair<int,int> pll;
    16 const int inf = 0x3f3f3f3f;
    17 const LL INF = 0x3f3f3f3f3f3f3f3f;
    18 const LL mod =  (int)1e9+7;
    19 const int N = 1e5 + 100;
    20 int F[N], Finv[N], inv[N];/// F是阶层 Finv是逆元的阶层
    21 void init(){
    22     inv[1] = 1;
    23     for(int i = 2; i < N; i++)
    24         inv[i] = (mod - mod/i) * 1ll * inv[mod % i] % mod;
    25     F[0] = Finv[0] = 1;
    26     for(int i = 1; i < N; i++){
    27         F[i] = F[i-1] * 1ll * i % mod;
    28         Finv[i] = Finv[i-1] * 1ll * inv[i] % mod;
    29     }
    30 }
    31 int comb(int n, int m){ /// C(n,m)
    32     if(m < 0 || m > n) return 0;
    33     return F[n] * 1ll * Finv[n-m] % mod * Finv[m] % mod;
    34 }
    35 int n, m, k, op, x, y;
    36 int dp[55][N];
    37 int add[N];
    38 vector<pll>  vc;
    39 int query(int x){
    40     int ret = dp[k][x];
    41     for(int i = 0; i < vc.size(); i++){
    42         if(vc[i].fi > x) continue;
    43         ret = (ret + 1ll * vc[i].se * comb(k-1+x-vc[i].fi,k-1)) % mod;
    44     }
    45     return ret;
    46 }
    47 void build(){
    48     //memset(add, 0, sizeof(add))
    49     //add[1] += dp[1][1];
    50     for(int i = 0; i < vc.size(); i++){
    51         x = vc[i].fi, y = vc[i].se;
    52         add[x] = (add[x] + y) % mod;
    53     }
    54     vc.clear();
    55     for(int i = 1; i <= n; i++){
    56         dp[1][i] = (dp[1][i-1] + add[i]) % mod;
    57         //add[i] = 0;
    58     }
    59     for(int i = 2; i <= k; i++)
    60         for(int j = 1; j <= n; j++)
    61             dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % mod;
    62 }
    63 int main(){
    64     init();
    65     scanf("%d%d%d", &n, &m, &k);
    66     while(m--){
    67         scanf("%d", &op);
    68         if(op){
    69             scanf("%d", &x);
    70             printf("%d
    ",query(x));
    71         }
    72         else{
    73             scanf("%d%d", &x, &y);
    74             vc.pb(pll(x,y));
    75             if(vc.size() == 2000)
    76                 build();
    77         }
    78     }
    79     return 0;
    80 }
    View Code

      

  • 相关阅读:
    MongoDB数据库学习总结
    windows及linux环境下永久修改pip镜像源的方法
    enumerate枚举函数
    sum求和函数
    zip拉链函数
    python实现面对面快传
    redis实现发布订阅
    python自定义classmethod
    Nginx为什么支持那么高的并发量?
    java进阶(28)--Map集合
  • 原文地址:https://www.cnblogs.com/MingSD/p/9528083.html
Copyright © 2011-2022 走看看