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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu 3577(线段树区间更新)

發布時間:2025/3/16 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu 3577(线段树区间更新) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


題意:輸入一個t,表示有t組測試數據;

????????? 接下來一行,輸入兩個數,k,m,其中k表示這個輛車最多可以坐這么多人,m表示有m次詢問能否上車;

????????? 每一次詢問,輸入兩個數a,b,表示該乘客能否在a站臺上車,b站臺下車,乘車區間為(a,b--),先后次序;

????????? 即我每次詢問,你就判斷在a站臺處將會有多少人還在車上,小于k則表示能夠上車,更新數據,反之不能上車;


解題思路:這道題很明顯就是線段樹的區間更新,即判斷線段的重疊次數。


按照劉汝佳書上寫的代碼WA了,不知道為什么。。。


#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 1e6+5; int add[maxn<<2],Max[maxn<<2],l,r,_max; int ans[maxn];void maintain(int o,int L,int R) {int lc = o*2,rc = o*2+1;Max[o] = 0;if(R > L){Max[o] = max(Max[lc],Max[rc]);}Max[o] += add[o]; }void update(int o,int L,int R,int v) {int lc = o*2, rc = o*2+1;if(l <= L && R <= r){add[o] += v;}else{int M = (L + R) >> 1;if(M >= l) update(lc,L,M,v);if(r > M) update(rc,M+1,R,v);}maintain(o,L,R); }void query(int o,int L,int R,int addv) {int lc = o*2, rc = o*2+1;if(l <= L && R <= r){_max = max(_max,Max[o] + addv);}else{int M = (L + R) >> 1;if(l <= M) query(lc,L,M,addv+add[lc]);if(r > M) query(rc,M+1,R,addv+add[rc]);} }int main() {int t,cas = 1,len;scanf("%d",&t);while(t--){memset(add,0,sizeof(add));memset(Max,0,sizeof(Max));len = 0;int k,q;scanf("%d%d",&k,&q);for(int i = 1; i <= q; i++){scanf("%d%d",&l,&r);r--;_max = 0;query(1,1,1000000,0);if(_max < k){update(1,1,1000000,1);ans[len++] = i;}}printf("Case %d:\n",cas++);for(int i = 0; i < len; i++)printf("%d ",ans[i]);printf("\n\n");}return 0; }



看了別人的代碼,采用了一種lazy思想,也就是用一層更新一層,如果我在某一層能夠找到符合要求的區間,那么就不更新它的子節點了,等到我需要它的子節點時,再把子節點更新了。。。總之是這樣的一種思想,結合代碼多思考下。。。


#include<iostream> #include<string> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N=1000005; int ans[N]; struct node {int l,r,v,lazy; }node[N<<2]; // 線段樹的空間大概是數組空間的4倍; void build(int l,int r,int numb) // 線段樹的建立; {node[numb].l=l;node[numb].r=r;node[numb].v=0;node[numb].lazy=0; // 用了lazy思想,提高了效率;if(l==r) return;int mid=(l+r)>>1;build(l,mid,numb<<1);build(mid+1,r,numb<<1|1); } void PushUp(int numb) // 往上往父節點方向更新數據;但是這里不是左右兒子的和,而是最大值,因為是站臺人數; {node[numb].v=max(node[numb<<1].v,node[numb<<1|1].v); } void PushDown(int numb) // 向下往左右兒子方向更新數據; {node[numb<<1].lazy+=node[numb].lazy;node[numb<<1|1].lazy+=node[numb].lazy;node[numb<<1].v+=node[numb].lazy;node[numb<<1|1].v+=node[numb].lazy;node[numb].lazy=0; // 更新完了要清零; } void Insert(int l,int r,int numb) // 插入更新數據; {if(node[numb].l>=l&&node[numb].r<=r) // 如果區間完全重合,則不需要再往下更新了,先保存起來,可以節約很多的時間(lazy思想){node[numb].v+=1;node[numb].lazy+=1;return;}if(node[numb].lazy) PushDown(numb); // 因為沒有找到完全重合的區間,所以要先更新下一層區間;int mid=(node[numb].r+node[numb].l)>>1;if(l>mid) Insert(l,r,numb<<1|1);else if(r<=mid) Insert(l,r,numb<<1);else{Insert(l,mid,numb<<1);Insert(mid+1,r,numb<<1|1);}PushUp(numb); // 最后還得往上返回,更新父節點區間; } int query(int l,int r,int numb) // 查詢區間l到r; {if(node[numb].l>=l&&node[numb].r<=r){return node[numb].v;}if(node[numb].lazy) PushDown(numb); // 道理同48行;int mid=(node[numb].r+node[numb].l)>>1;if(l>mid) return query(l,r,numb<<1|1);else if(r<=mid) return query(l,r,numb<<1);else{return max(query(l,mid,numb<<1),query(mid+1,r,numb<<1|1)); // 道理同28行;} } int main() {int t,Case=1,len=0,k,m,a,b;scanf("%d",&t);while(t--){len=0;memset(ans,0,sizeof(ans));scanf("%d%d",&k,&m);build(1,1000000,1);for(int i=0;i<m;i++){scanf("%d%d",&a,&b);b--; // 這里有一個問題,就是乘客從a上車,b下車,所以乘客在車上的區間為(a,b--);if(query(a,b,1)<k){ // 表示可以上車;ans[len++]=i+1;Insert(a,b,1);}}printf("Case %d:\n",Case++);for(int i=0; i<len; i++) printf("%d ",ans[i]);printf("\n\n");}return 0; }

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的hdu 3577(线段树区间更新)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。