牛客練習賽28 B 資料結構

2021-08-29 04:05:24 字數 4242 閱讀 3362

題目描述:

qn姐姐最好了~

qn姐姐給你了乙個長度為n的序列還有m次操作讓你玩,

1 l r 詢問區間[l,r]內的元素和

2 l r 詢問區間[l,r]內的元素的平方

3 l r x 將區間[l,r]內的每乙個元素都乘上x

4 l r x 將區間[l,r]內的每乙個元素都加上x

第一行兩個數n,m

接下來一行n個數表示初始序列

就下來m行每行第乙個數為操作方法opt,

若opt=1或者opt=2,則之後跟著兩個數為l,r

若opt=3或者opt=4,則之後跟著三個數為l,r,x

操作意思為題目描述裡說的

對於每乙個操作1,2,輸出一行表示答案
示例1

5 6

1 2 3 4 5

1 1 5

2 1 5

3 1 2 1

4 1 3 2

1 1 4

2 2 3

15

5516

41

對於100%的資料 n=10000,m=200000 (注意是等於號)

保證所有詢問的答案在long long 範圍內

出題人題解:

顯然,線段樹

記錄4個東西,區間和tree[root][0],區間平方和 tree[root][1],乘法懶標記 add2[root],加法懶標記add1[root] 。

查詢的話就是常規查詢,打標記就是線段樹2板子一樣,

初值:add1[root]=0,add2[root]=1;

加法:add1[root]+=dx

乘法:add2[root]*=dx;

然後考慮更新答案

當前區間[l,r] ,當前節點root,這裡面每個元素都變成了( a[i]為更新後, x[i]為更新前)

所以

利用線段樹處理區間和與區間平方和

利用性質(a+b)^2

區間和的話比較容易了,

然後lazy有點麻煩

然後就標準線段樹板子

線段樹模板:

#include#include#includeusing namespace std;

#define maxn 10005

#define lson l,mid,root<<1

#define rson mid+1,r,root<<1|1

long long n,m,tree[maxn<<2][2],add1[maxn<<2],add2[maxn<<2];

void pushup(long long root)

void pushdown1(long long l,long long r,long long root)

}void pushdown2(long long l,long long r,long long root)

}void build(long long l,long long r,long long root)

long long mid=(l+r)>>1;

build(lson);

build(rson);

pushup(root);

}void update1(long long l,long long r,long long c,long long l,long long r,long long root)

long long mid = (l+r)/2;

pushdown2(mid-l+1,r-mid,root); pushdown1(mid-l+1,r-mid,root);

if(l<=mid)

update1(l,r,c,lson);

if(r>mid)

update1(l,r,c,rson);

pushup(root);

}void update2(long long l,long long r,long long c,long long l,long long r,long long root)

long long mid = (l+r)/2;

pushdown2(mid-l+1,r-mid,root); pushdown1(mid-l+1,r-mid,root);

if(l<=mid)

update2(l,r,c,lson);

if(r>mid)

update2(l,r,c,rson);

pushup(root);

}long long query(long long l,long long r,long long c,long long l,long long r,long long root)

long long ans=0,mid=(l+r)>>1;

pushdown2(mid-l+1,r-mid,root); pushdown1(mid-l+1,r-mid,root);

if(l<=mid)

ans+=query(l,r,c,lson);

if(r>mid)

ans+=query(l,r,c,rson);

return ans;

}int main()

else if(op==3||op==4)

}return 0;

}

**:題解

第二種。。。

#include#include#include#include#include#define n 100005

using namespace std;

typedef long long ll;

struct node

tree[n];

ll a[10005];

int n, m;

void build(int g, int l, int r)

int mid = (l + r) >> 1;

build(g * 2, l, mid);

build(g * 2 + 1, mid + 1, r);

tree[g].mulzy = 1;

tree[g].sum = tree[g * 2].sum + tree[g * 2 + 1].sum;

tree[g].mul = tree[g * 2].mul + tree[g * 2 + 1].mul;

}void updata(int p, int l, int r)

void insert(int p, int l, int r, int a, int b, ll x, int opt)

updata(p,l,r);

if (mid >= b)

insert(p * 2, l, mid, a, b, x, opt);

else if (a > mid)

insert(p * 2 + 1, mid + 1, r, a, b, x, opt);

else

tree[p].sum = tree[p * 2].sum + tree[p * 2 + 1].sum;

tree[p].mul = tree[p * 2].mul + tree[p * 2 + 1].mul;

}ll get_sum(int p, int l, int r, int a, int b, int opt)

updata(p, l, r);

if (mid >= b)

return get_sum(p * 2, l, mid, a, b, opt);

else if (a > mid)

return get_sum(p * 2 + 1, mid + 1, r, a, b, opt);

else return get_sum(p * 2, l, mid, a, mid, opt) + get_sum(p * 2 + 1, mid + 1, r, mid + 1, b, opt);

}int main()

if (opt == 3 || opt == 4)

}return 0;

}

《牛客練習賽28 B》

這題主要就是多了乙個平方和的操作。我們維護平方和的值的時候。需要注意在下放的時候,要先把乘法之後的sum1算出來,這對算sum1最終的值沒有影響。但是對sum2的值有影響。因為我們在計算中就在更新adtag的值,所以這個adtag它的sum1應該最終化。includeusing namespace ...

資料結構 線段樹 牛客練習賽28B

op 1 sum op 2 sum2 平方和 op 3 mul op 4 add 2個lazy標記 include include using namespace std define lc rt 1 define rc rt 1 1 define mid l r 2 typedef long lo...

牛客練習賽28 B 複習線段樹 )

description qn姐姐給你了乙個長度為n的序列還有m次操作讓你玩,1 l r 詢問區間 l,r 內的元素和 2 l r 詢問區間 l,r 內的元素的平方和 3 l r x 將區間 l,r 內的每乙個元素都乘上x 4 l r x 將區間 l,r 內的每乙個元素都加上x input n,mop...