牛客多校第9场H Prefix Sum

这题正解是线段树上打等差数列的tag,然后维护。不过我看不太懂= =,队友想起了卢总讲过的big-small分块暴力思想,对于一个x位置加了一个y,a[k][idx]就加了C(idx+k-x-1,k-1),我们开一个队列长度为sz保存一蛤操作,超过sz就把队列中的+操作放进a[0]里面去,然后跑n*k,算出a[k],把队列清0,如果没超过sz的询问,直接a[k][idx]+队列中每一个操作对a[k][idx]的影响,复杂度为n*k*m/sz+sz*m,然后均值不等式一蛤,sz=sqrt(n*k)的时候比较优秀,所以2000左右就行了,队友开了1800,然后就开始WA了,还好我今早补了昨天hdu的组合数,组合数数组开小了一次,他这道题组合数也开小了,idx+k-x-1虽然不要开2倍,不过还是要开1e5+40的

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mk make_pair
#define X first
#define Y second
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define mem(a,x) memset(a,x,sizeof(a))
typedef long long LL;
 
const int maxn=2e5+5,sz=1800,mod=1e9+7;
int n,m,k,opt,x,y;
LL a[41][maxn];
int v[maxn][2];
LL inv[maxn],fac[maxn];
int cnt=0;
inline void init()   
{   
    inv[0] = fac[0] = inv[1] = fac[1] = 1;   
    for(register int i = 1; i < maxn; ++i)   
    fac[i] = fac[i - 1] * i % mod;   
    for(register int i = 2; i < maxn; ++i)   
    inv[i] = (mod - (mod / i)) * inv[mod % i] % mod;   
    for(register int i = 1; i < maxn; ++i)   
    inv[i] = inv[i - 1] * inv[i] % mod;    
} 
 
inline LL C(int n, int m)//求组合数 C n,m    
{   
    if(n<m)return 0;
    return (fac[n] * inv[m] % mod) * inv[n - m] %mod;    
}   
 
inline void rebuild()
{
    for(register int i=0;i<cnt;++i)
        a[0][v[i][0]]=(a[0][v[i][0]]+v[i][1])%mod;
    for(register int i=1;i<=k;++i)
        for(register int j=1;j<=n;++j)
            a[i][j]=(a[i-1][j]+a[i][j-1])%mod;
    cnt=0;
}
 
int main()
{
    //freopen("1008.in","r",stdin);
    //freopen("std.out","w",stdout);
    init();
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        //memset(a,0,sizeof(a));
        for(register int i=0;i<=k;++i)
            for(register int j=1;j<=n;++j)
                a[i][j]=0;
        cnt=0;
        for(register int i=1;i<=m;++i)
        {
            scanf("%d",&opt);
            if(!opt)
            {
                if(cnt==sz)rebuild();
                scanf("%d%d",&x,&y);
                v[cnt][0]=x;
                v[cnt][1]=y;
                ++cnt;
            }
            else
            {
                int idx;
                scanf("%d",&idx);
                LL res=a[k][idx];
                for(register int j=0;j<cnt;++j)
                {
                    LL x=v[j][0],y=v[j][1];
                    if(x>idx)continue;
                    LL N=k+idx-x-1,M=k-1;
                    res=(res+C(N,M)*y%mod)%mod;                
                }
                printf("%lld\n",res);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/81749844