题目链接:​​The Trip On Abandoned Railway​

题目大意:给你一个长度为n的数列和一个公差d,然后m个操作,操作分为两种,第一种操作有一个x和y,代表从x开始的每个数按照等差数列开始加,x这个位置加上y,x+1这个位置加上y+d,x+2这个位置加上y+2*d,依次递推;第二种操作有一个x,代表把这个位置的数模1e9+7后输出,并且这个位置变成零

题目思路:数据范围很大,所以考虑使用线段树,考虑每次更新x到n加上y,然后i从x+1到n,每次更新i到n加上d,但是这样的复杂度会超时,因为每次更新的时候会多一个n,然后西瓜给了个前缀和的做法,线段树和树状数组同时用,每次进行操作1的时候,用树状数组将这个点更新为y(用于处理首项和的问题),然后用线段树把整个【x+1,n】的值全部加上1(用于判断有多少个d的前缀和),然后操作二的时候,直接用树状数组统计一下x之前所有的和,实际上就是累加了多少个首项,然后用线段树取【1,x】里面的1然后乘以一个d就好了,最后加上a[i]就好,最后a[i]要减去这个值,大概做法就这样(前排膜西瓜巨的神做法)

#include <bits/stdc++.h>
#define eps 1e-6
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e15 + 8;

ll a[maxn];
ll c[maxn], n, d;
int lowbit(int x) {
return x & -x;
}

void up(int x, ll d) {
while (x < maxn) {
c[x] += d;
c[x] %= mod;
x += lowbit(x);
}
}

ll getsum(int x) {
int ans = 0;
while (x) {
ans += c[x];
ans %= mod;
x -= lowbit(x);
}
return ans;
}


struct TREE {
ll l, r, val, lazy;
void fun(ll tmp) {
lazy += tmp;
val += (r - l + 1) * tmp;
}
} tre[maxn*4];

void PushDown(int id) {
if (tre[id].lazy) {
tre[id<<1].fun(tre[id].lazy);
tre[id<<1|1].fun(tre[id].lazy);
tre[id].lazy = 0;
}
}

void PushUp(int id) {
tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
}

void build(int id, int l, int r) {
tre[id].l = l, tre[id].r = r, tre[id].lazy = 0;
if (l == r) tre[id].val = 0;
else {
int mid = (l + r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
PushUp(id);
}
}

void update(int id, int st, int ed, int val) {
int l = tre[id].l, r = tre[id].r;
if (st <= l && ed >= r) tre[id].fun(val);
else {
PushDown(id);
int mid = l + r >> 1;
if (st <= mid) update(id<<1, st, ed, val);
if (ed > mid) update(id<<1|1, st, ed, val);
PushUp(id);
}
}

ll query(int id, int st, int ed) {
int l = tre[id].l, r = tre[id].r;
if (st <= l && ed >= r) return tre[id].val;
else {
PushDown(id);
int mid = l + r >> 1;
ll sum1 = 0, sum2 = 0;
if (st <= mid) sum1 = query(id<<1, st, ed);
if (ed > mid) sum2 = query(id<<1|1, st, ed);
PushUp(id);
return sum1 + sum2;
}
}

void solve() {
int m;
scanf("%lld%d%lld",&n,&m,&d);
for (int i = 1; i <= n; i++) scanf("%lld", a + i);
memset(c, 0, sizeof(c));
build(1, 1, n);
ll tot = 0;
while (m--) {
int op, x, y; scanf("%d%d", &op, &x);
if (op == 1) {
scanf("%d", &y);
up(x, y);
update(1, x + 1, n , 1);
}
else {
ll tmp = getsum(x) + query(1, 1, x) * d + a[x];
printf("%lld\n", tmp % mod);
a[x] -= tmp;
//printf("a[x] = %d\n",a[x]);
}
}
}

int main(){
freopen("in.txt", "r", stdin);
int t = 1;
scanf("%d",&t);
while (t--) {
solve();
}
return 0;
}