RT,评测记录如下戳我。按理这种线段树的题,过了九个点,这个点也过了66次询问,而且全是大数据,出现这种情况就很糟糕啊。
思路不知道和题解一不一样,因为是等差数列,所以我考虑维护这个线段的首项和公差,这样就可以快速地pushdown。代码有注释,码风不错,求大佬帮忙,谢谢!
ll A[maxn], N, Q; //数组
struct SegmentTree {
ll x, start, comdif;
} T[maxn << 2]; //segment tree的和,这个线段的lazy tag -> 数列的首项,数列的公差
//建树
void build(ll s, ll t, ll p) {
if (s == t) {
T[p].x = A[s];
return ;
}
ll m = (s + t) >> 1;
build(s, m, p << 1), build(m + 1, t, p << 1 | 1);
T[p].x = T[p << 1].x + T[p << 1 | 1].x;
}
//pushdown操作
void pushdown(ll s, ll t, ll p) {
ll m = (s + t) >> 1;
T[p << 1].start += T[p].start, T[p << 1 | 1].start += (T[p].start + T[p].comdif * (m + 1 - s)); //首项 + 线段对应的首项
T[p << 1].comdif += T[p].comdif, T[p << 1 | 1].comdif += T[p].comdif; //公差相加
T[p << 1].x += (T[p].start * 2 + T[p].comdif * (m - s)) * (m - s + 1) / 2; //第一个子线段求和
T[p << 1 | 1].x += (T[p].start + T[p].comdif * (m + 1 - s) + T[p].start + T[p].comdif * (t - s)) * (t - m) / 2; //第二个子线段求和
T[p].start = 0, T[p].comdif = 0; //清零
}
void update(ll l, ll r, ll s, ll t, ll p, ll val, ll K) {
if (l <= s && r >= t) {
T[p].x += (K + val * (s - l) + K + (t - l) * val) * (t - s + 1) / 2; //K代表题目中的K,val是公差,给他加上去
T[p].comdif += val; //公差更新
T[p].start += (K + (s - l) * val); //首项更新
return ;
}
ll m = (s + t) >> 1;
if (T[p].start) pushdown(s, t, p);
if (l <= m) update(l, r, s, m, p << 1, val, K);
if (r > m) update(l, r, m + 1, t, p << 1 | 1, val, K);
T[p].x = T[p << 1].x + T[p << 1 | 1].x;
}
ll query(ll l, ll s, ll t, ll p) { //单点查询
if (s == t) return T[p].x;
ll m = (s + t) >> 1;
if (T[p].start) pushdown(s, t, p);
if (l <= m) return query(l, s, m, p << 1);
return query(l, m + 1, t, p << 1 | 1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N >> Q;
for (ll i = 1; i <= N; i++)
cin >> A[i];
build(1, N, 1);
ll x, c1, c2, val, K;
while (Q--) {
cin >> x;
if (x == 1) {
cin >> c1 >> c2 >> K >> val;
update(c1, c2, 1, N, 1, val, K);
}
else if (x == 2) {
cin >> c1;
cout << query(c1, 1, N, 1) << endl;
}
}
return 0;
}