1.P1438 无聊的数列 - 洛谷 | 计算机科学教育新生态
线段树 + 差分,一开始的思路是直接将整个等差数列加到线段树中,但是pushdown不好维护于是改变思路,想到我们可以去维护a的差分数组,这样一来对[l , r]加上一个首项为看,公差为d的等差数列其实就是在l上加k,[l + 1 ~ r]上加d,之后我们求第p项也转变成求[1 ~ p]的区间和即可,一开始多尝试新思路,不要在困难的思路上折磨自己,多想少code
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<ll , ll> pii;
typedef pair<int , string> pis;
const int N = 1e5 + 10,inf = 0x3f3f3f3f,mod = 1e9 + 7;
const double pi = 3.1415926535898;struct node
{int l,r;ll sum,add;
}tr[4 * N];int n,m;
ll a[N],b[N];void pushup(node &u,node &l,node &r)
{u.sum = l.sum + r.sum;
}void pushup(int u)
{pushup(tr[u] , tr[u << 1] , tr[u << 1 | 1]);
}void pushdown(node &u,node &l,node &r)
{if(u.add){l.sum += (l.r - l.l + 1) * u.add;r.sum += (r.r - r.l + 1) * u.add;l.add += u.add,r.add += u.add;u.add = 0;}
}void pushdown(int u)
{pushdown(tr[u] , tr[u << 1] , tr[u << 1 | 1]);
}void build(int u,int l,int r)
{if(l == r){tr[u] = {l , r , b[l] , 0};}else{tr[u] = {l , r};int mid = (l + r) / 2;build(u << 1 , l , mid);build(u << 1 | 1 , mid + 1 , r);pushup(u);}
}void modify(int u,int l,int r,ll d)
{if(tr[u].l >= l && tr[u].r <= r){tr[u].sum += (tr[u].r - tr[u].l + 1) * d;tr[u].add += d;}else{int mid = (tr[u].l + tr[u].r) / 2;pushdown(u);if(l <= mid){modify(u << 1 , l , r , d);}if(r > mid){modify(u << 1 | 1 , l , r , d);}pushup(u);}
}node query(int u,int l,int r)
{if(tr[u].l >= l && tr[u].r <= r){return tr[u];}else{int mid = (tr[u].l + tr[u].r) / 2;pushdown(u);if(r <= mid){return query(u << 1 , l , r);}else if(l > mid){return query(u << 1 | 1 , l , r);}else{node left = query(u << 1 , l , r);node right = query(u << 1 | 1 , l , r);node res;pushup(res , left , right);return res;}}
}int main()
{std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i = 1 ; i <= n ; i++){cin>>a[i];b[i] = a[i] - a[i - 1];} build(1 , 1 , n);while(m--){int op;cin>>op;if(op == 1){ll l,r,d,k;cin>>l>>r>>k>>d;modify(1 , l , l , k);if(r + 1 <= n){modify(1 , r + 1 , r + 1 , - k);}if(r > l){modify(1 , l + 1 , r , d);if(r + 1 <= n){modify(1 , r + 1 , r + 1 , -d * (r - l));} }}else{int p;cin>>p;cout<<query(1 , 1 , p).sum<<"\n";}}return 0;
}// 5 8
// 1 2 3 4 5
// 1 2 4 1 2
// 1 3 5 4 9
// 1 1 2 1 2
// 2 1
// 2 2
// 2 3
// 2 4
// 2 5// 2
// 6
// 10
// 22
// 27