日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【北航oj】(线段树取模运算)

發(fā)布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【北航oj】(线段树取模运算) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題干:

https://buaacoding.cn/contest-ng/index.html#/334/problems

K?wjj 的自動售貨機

時間限制:1000ms ? 內(nèi)存限制:131072kb

通過率:14/26?(53.85%)??? 正確率:14/119?(11.76%)

wjj 最近很看好線下實體銷售的行業(yè), 他覺得可以先投資自動售貨機來試試水。

于是他在北航的新主樓中安裝了一臺可以售賣?nn?種物品的售貨機, 第?ii?種物品共有?aiai?個。

為了方便用戶,用戶每次購買時, 可以選定某個區(qū)間?[l,r][l,r]?內(nèi)的種類, 然后自動售貨機根據(jù)選定的區(qū)間進行出貨。

記?al,al+1,?,ar?1,aral,al+1,?,ar?1,ar?非零值中的最小值為?xx, 每種物品會以?xx?個為一組、盡可能多地出貨; 即出貨后,物品數(shù)量?ai←(aimodx),?i∈[l,r]ai←(aimodx),?i∈[l,r]。

wjj 最終按順序記錄了?qq?個這樣的區(qū)間信息。 他希望你能幫他計算,每次出貨前和出貨后,選定區(qū)間內(nèi)的剩余物品數(shù)量的總和; 即分別以每次出貨前和出貨后的?aiai,計算?∑ri=lai∑i=lrai。

輸入

第一行包含一個正整數(shù)?TT(1≤T≤101≤T≤10),表示有?TT?組測試數(shù)據(jù)。

接下來依次給出每組測試數(shù)據(jù)。對于每組測試數(shù)據(jù):

第一行,包含兩個整數(shù)?nn?和?qq,含義見題目描述。

第二行,nn?個空格分隔的整數(shù),依次表示序列的每一項。0≤ai≤10130≤ai≤1013(1≤i≤n1≤i≤n)。

接下來?qq?行,每行表示一組詢問,格式如下:

  • L R

1≤L≤R≤n1≤L≤R≤n。

對于所有的測試數(shù)據(jù),滿足?∑n,∑q≤2×105∑n,∑q≤2×105。

輸出

對于每組數(shù)據(jù),對于每個詢問,輸出空格分隔的兩個整數(shù)表示答案。

輸入樣例

1 5 2 5 4 2 2 10 1 5 1 5

輸出樣例

23 1 1 0

題目大意:

? ?n個數(shù),q次詢問,每次詢問給出一段區(qū)間,找到區(qū)間內(nèi)非零的最小的數(shù)x,對該區(qū)間的每個數(shù)都更新為a[i]取模x,對于每次操作,輸出更新前和更新后的區(qū)間和。

解題報告:

? ?由于取模運算可以使得改數(shù)字最少減小一半(證明很簡單),所以對于每個數(shù)字最多l(xiāng)ogn次就降為0,所以對于更新操作可以直接暴力。對于查詢最小值,注意一下排除為0的情況就可以了。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; const ll INF = 9223372036854775807; int n,q; ll a[MAX]; struct TREE {int l,r;ll val;//區(qū)間和 ll minn; } tree[MAX<<2]; void pushup(int cur) {ll t1=tree[cur*2].minn;ll t2=tree[cur*2+1].minn;if(t1 == 0) tree[cur].minn = t2;else if(t2 == 0) tree[cur].minn = t1;else tree[cur].minn = min(t1,t2);tree[cur].val = tree[cur*2].val + tree[cur*2+1].val; } void build(int l,int r,int cur) {tree[cur].l = l,tree[cur].r = r;if(l == r) {tree[cur].minn = tree[cur].val = a[r];return;}int m = (l+r)>>1;build(l,m,cur*2);build(m+1,r,cur*2+1);pushup(cur); } ll qMin(int pl,int pr,int cur) {//查詢區(qū)間最小值 if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].minn;}ll tmp1 = INF,tmp2 = INF;if(pl <= tree[cur*2].r) tmp1 = qMin(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qMin(pl,pr,cur*2+1);if(tmp1 == 0) {if(tmp2 == INF) tmp2=0;return tmp2;}if(tmp2 == 0) {if(tmp1 == INF) tmp1=0;return tmp1;}return min(tmp1,tmp2); }ll qSum(int pl,int pr,int cur) {//查詢區(qū)間和if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].val;}ll tmp1 = 0,tmp2 = 0;if(pl <= tree[cur*2].r) tmp1 = qSum(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qSum(pl,pr,cur*2+1);return tmp1+tmp2; } void update(int pl,int pr,ll val,int cur) {if(tree[cur].minn == 0) return ;if(tree[cur].l == tree[cur].r) {tree[cur].val%=val;tree[cur].minn%=val;return;}if(pl <= tree[cur*2].r) update(pl,pr,val,cur*2);if(pr >= tree[cur*2+1].l) update(pl,pr,val,cur*2+1);pushup(cur); } int main() {int t;cin>>t;while(t--) {scanf("%d%d",&n,&q);for(int i = 1; i<=n; i++) {scanf("%lld",a+i);}build(1,n,1);while(q--) {int l,r;scanf("%d%d",&l,&r);ll tmp = qMin(l,r,1);ll ans1 = qSum(l,r,1);ll ans2;if(tmp == 0) ans2 = ans1;else {update(l,r,tmp,1);ans2 = qSum(l,r,1);}printf("%lld %lld\n",ans1,ans2);}}return 0 ; }

WA代碼1:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; const ll INF = 9223372036854775807; int n,q; ll a[MAX]; struct TREE {int l,r;ll val;//區(qū)間和 ll minn; } tree[MAX<<2]; void pushup(int cur) {ll t1=tree[cur*2].minn;ll t2=tree[cur*2+1].minn;if(t1 == 0) tree[cur].minn = t2;else if(t2 == 0) tree[cur].minn = t1;else tree[cur].minn = min(t1,t2);tree[cur].val = tree[cur*2].val + tree[cur*2+1].val; } void build(int l,int r,int cur) {tree[cur].l = l,tree[cur].r = r;if(l == r) {tree[cur].minn = tree[cur].val = a[r];return;}int m = (l+r)>>1;build(l,m,cur*2);build(m+1,r,cur*2+1);pushup(cur); } ll qMin(int pl,int pr,int cur) {//查詢區(qū)間最小值 if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].minn;}ll tmp1 = INF,tmp2 = INF;if(pl <= tree[cur*2].r) tmp1 = qMin(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qMin(pl,pr,cur*2+1);return min(tmp1,tmp2); }ll qSum(int pl,int pr,int cur) {//查詢區(qū)間和if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].val;}ll tmp1 = 0,tmp2 = 0;if(pl <= tree[cur*2].r) tmp1 = qMin(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qMin(pl,pr,cur*2+1);return tmp1+tmp2; } void update(int pl,int pr,ll val,int cur) {if(tree[cur].minn == 0) return ;if(tree[cur].l == tree[cur].r) {tree[cur].val%=val;tree[cur].minn%=val;return;}if(pl <= tree[cur*2].r) update(pl,pr,val,cur*2);if(pr >= tree[cur*2+1].l) update(pl,pr,val,cur*2+1);pushup(cur); } int main() {int t;cin>>t;while(t--) {scanf("%d%d",&n,&q);for(int i = 1; i<=n; i++) {scanf("%lld",a+i);}build(1,n,1);while(q--) {int l,r;scanf("%d%d",&l,&r);ll tmp = qMin(l,r,1);ll ans1 = qSum(l,r,1);ll ans2;if(tmp == 0) ans2 = ans1;else {update(l,r,tmp,1);ans2 = qSum(l,r,1);} printf("%lld %lld\n",ans1,ans2);}}return 0 ; }

WA代碼2::

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; const ll INF = 9223372036854775807; int n,q; ll a[MAX]; struct TREE {int l,r;ll val;//區(qū)間和 ll minn; } tree[MAX<<2]; void pushup(int cur) {ll t1=tree[cur*2].minn;ll t2=tree[cur*2+1].minn;if(t1 == 0) tree[cur].minn = t2;else if(t2 == 0) tree[cur].minn = t1;else tree[cur].minn = min(t1,t2);tree[cur].val = tree[cur*2].val + tree[cur*2+1].val; } void build(int l,int r,int cur) {tree[cur].l = l,tree[cur].r = r;if(l == r) {tree[cur].minn = tree[cur].val = a[r];return;}int m = (l+r)>>1;build(l,m,cur*2);build(m+1,r,cur*2+1);pushup(cur); } ll qMin(int pl,int pr,int cur) {//查詢區(qū)間最小值 if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].minn;}ll tmp1 = INF,tmp2 = INF;if(pl <= tree[cur*2].r) tmp1 = qMin(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qMin(pl,pr,cur*2+1);if(tmp1 == 0) return tmp2;if(tmp2 == 0) return tmp1;return min(tmp1,tmp2); }ll qSum(int pl,int pr,int cur) {//查詢區(qū)間和if(pl <= tree[cur].l && pr >= tree[cur].r) {return tree[cur].val;}ll tmp1 = 0,tmp2 = 0;if(pl <= tree[cur*2].r) tmp1 = qMin(pl,pr,cur*2);if(pr >= tree[cur*2+1].l) tmp2 = qMin(pl,pr,cur*2+1);return tmp1+tmp2; } void update(int pl,int pr,ll val,int cur) {if(tree[cur].minn == 0) return ;if(tree[cur].l == tree[cur].r) {tree[cur].val%=val;tree[cur].minn%=val;return;}if(pl <= tree[cur*2].r) update(pl,pr,val,cur*2);if(pr >= tree[cur*2+1].l) update(pl,pr,val,cur*2+1);pushup(cur); } int main() {int t;cin>>t;while(t--) {scanf("%d%d",&n,&q);for(int i = 1; i<=n; i++) {scanf("%lld",a+i);}build(1,n,1);while(q--) {int l,r;scanf("%d%d",&l,&r);ll tmp = qMin(l,r,1);ll ans1 = qSum(l,r,1);ll ans2;if(tmp == 0) ans2 = ans1;else {update(l,r,tmp,1);ans2 = qSum(l,r,1);} printf("%lld %lld\n",ans1,ans2);}}return 0 ; }

總結(jié):

WA了好幾發(fā),,

首先RE因為沒有開四倍。

1WA首先是沒有所有的變量都開longlong,后來一個一個變量檢查的。

2WA是INF設(shè)置的不夠大,因為單個數(shù)據(jù)是1e13,而總共2e5個數(shù),所以最大可能值是2e18,所以保險起見就設(shè)置INF為9e18好了。

3WA在求最小值的時候不太對,(也就是WA代碼1那樣寫的)這樣會導(dǎo)致只要有一個兒子節(jié)點的minn是0,就直接返回0了。

4WA在求最小值的時候不太對,因為這樣有可能返回INF,比如左子樹的minn是0,右子樹的minn是2,那么應(yīng)該返回 2,但是這樣的話就返回INF了。。。

5WA在qSum的時候,,,里面遞歸竟然寫成了qMin。。。我再也不復(fù)制粘貼了55555.

總結(jié)

以上是生活随笔為你收集整理的【北航oj】(线段树取模运算)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。