1. 程式人生 > >codevs 1082 線段樹練習3 (線段樹)

codevs 1082 線段樹練習3 (線段樹)

ace des 兩種 ++ math 如果 input 題目 ret

題目:

題目描述 Description

給你N個數,有兩種操作:

1:給區間[a,b]的所有數增加X

2:詢問區間[a,b]的數的和。

輸入描述 Input Description

第一行一個正整數n,接下來n行n個整數,

再接下來一個正整數Q,每行表示操作的個數,

如果第一個數是1,後接3個正整數,

表示在區間[a,b]內每個數增加X,如果是2,

表示操作2詢問區間[a,b]的和是多少。

pascal選手請不要使用readln讀入

輸出描述 Output Description

對於每個詢問輸出一行一個答案

樣例輸入 Sample Input

3

1

2

3

2

1 2 3 2

2 2 3

樣例輸出 Sample Output

9

數據範圍及提示 Data Size & Hint

數據範圍

1<=n<=200000

1<=q<=200000


思路:區間修改 區間修改 線段樹模板題 數據範圍有所提升 爆了int 要用long long
代碼:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include 
<string> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const int maxn=2e5+10; int n,m,x,y,v,op; ll ans; ll a[maxn]; struct node{ int l,r,lazy; ll w; }tree[maxn<<2
]; void build(int l,int r,int rt){ tree[rt].l=l; tree[rt].r=r; if(l==r){ tree[rt].w=a[l]; return; } int mid=(l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); tree[rt].w=tree[rt*2].w+tree[rt*2+1].w; } void pushdown(int rt){ tree[rt*2].lazy+=tree[rt].lazy; tree[rt*2+1].lazy+=tree[rt].lazy; tree[rt*2].w+=1ll*tree[rt].lazy*(tree[rt*2].r-tree[rt*2].l+1); tree[rt*2+1].w+=1ll*tree[rt].lazy*(tree[rt*2+1].r-tree[rt*2+1].l+1); tree[rt].lazy=0; } void update(int rt){ if(tree[rt].l>=x && tree[rt].r<=y){ tree[rt].w+=1ll*v*(tree[rt].r-tree[rt].l+1); tree[rt].lazy+=v; return; } if(tree[rt].lazy) pushdown(rt); int mid=(tree[rt].l+tree[rt].r)/2; if(x<=mid) update(rt*2); if(y>mid) update(rt*2+1); tree[rt].w=tree[rt*2].w+tree[rt*2+1].w; } void query(int rt){ if(tree[rt].l>=x && tree[rt].r<=y){ ans+=tree[rt].w; return; } if(tree[rt].lazy) pushdown(rt); int mid=(tree[rt].l+tree[rt].r)/2; if(x<=mid) query(rt*2); if(y>mid) query(rt*2+1); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } build(1,n,1); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d%d",&x,&y,&v); update(1); } if(op==2){ ans=0; scanf("%d%d",&x,&y); query(1); printf("%lld\n",ans); } } return 0; }

codevs 1082 線段樹練習3 (線段樹)