简单的线段树,由于我对lazy标记还是不熟,花了点时间。。。。像这种题目,query和updata都要加上pushdown并更新父节点。注意结果会爆int。。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 400005 #define eps 1e-6 #define mod 1000000007 #define INF 99999999 #define lowbit(x) (x&(-x)) typedef long long LL; using namespace std; LL num[maxn]; LL mark[maxn]; LL segtree[maxn]; LL ql, qr, k; LL n, m, ans; char s[10]; void build(LL o, LL L, LL R) { mark[o]=0; if(L==R){ segtree[o]=num[L]; return; } int mid=(L+R)>>1; build(o<<1, L, mid); build(o<<1 | 1, mid+1, R); segtree[o]=segtree[o<<1]+segtree[o<<1 | 1]; } void pushdown(LL o, LL L, LL R) { if(!mark[o]) return; int mid=(L+R)>>1; segtree[o<<1]+=(mid-L+1)*mark[o]; segtree[o<<1 | 1]+=(R-mid)*mark[o]; mark[o<<1]+=mark[o]; mark[o<<1 | 1]+=mark[o]; mark[o]=0; } void query(LL o, LL L, LL R) { if(ql<=L && qr>=R){ ans+=segtree[o]; return; } pushdown(o, L, R); int mid=(R+L)>>1; if(ql<=mid) query(o<<1, L, mid); if(qr>mid) query(o<<1 | 1, mid+1, R); segtree[o]=segtree[o<<1]+segtree[o<<1 | 1]; } void updata(LL o, LL L, LL R) { if(ql<=L && qr>=R){ mark[o]+=k; segtree[o]+=k*(R-L+1); return; } pushdown(o, L, R); int mid=(R+L)>>1; if(ql<=mid) updata(o<<1, L, mid); if(qr>mid) updata(o<<1 | 1, mid+1, R); segtree[o]=segtree[o<<1]+segtree[o<<1 | 1]; } void solve(void) { while(m--){ scanf("%s",s); if(s[0]=='Q'){ scanf("%lld%lld",&ql,&qr); ans=0; query(1, 1, n); printf("%lld\n", ans); } else{ scanf("%lld%lld%lld",&ql,&qr,&k); updata(1, 1, n); } } } int main(void) { while(scanf("%lld%lld",&n,&m)!=EOF){ for(int i=1;i<=n;i++) scanf("%lld",&num[i]); build(1, 1, n); solve(); } return 0; }