这题正解是线段树上打等差数列的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;
}