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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

hdu 3954(线段树区间更新)

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

轉載標記處:http://www.cnblogs.com/wang-jue/articles/2920341.html


思路:這道題所得到的經驗與每個英雄的等級有關,一般的可能就用線段樹一直更新到每一個英雄,但這樣肯定會超時的。所以我就在想如何使用lazy思想,我發現如果這一段區間內的英雄都已經是最高等級了,那么這一段內肯定是可以用lazy標記的,寫完之后TLE了。于是搜到這篇博客,他最開始的思路也是和我一樣。這里其實有一個隱含的信息,如果這一段區間內的英雄都沒有能夠升級的,那么毫無疑問這一段區間內是可以用lazy標記的,如果這一段區間內有英雄要升級的話,那么就更新到葉子節點。這樣我們就需要多增加一個域,表示這段區間內如果有英雄要升級,他所需要的最少經驗。仔細想想,如果這一段區間沒有英雄要升級,那么這段區間內的最大經驗值肯定是直接加上最大的等級*倍率即可。所以lazy只需要記錄每次輸入的倍率即可。這是這道題最難想到的地方。


先來份我的TLE的代碼:

#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 10005; struct Segment {int l,r;int max_exp,rank;int lazy,cover; }tree[maxn<<2]; int n,k,m,exprience[15];void build(int rt,int l,int r) {tree[rt].l = l, tree[rt].r = r;tree[rt].rank = 1;tree[rt].max_exp = tree[rt].lazy =tree[rt].cover = 0;if(l == r) return;int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); }void PushDown(int rt) {if(tree[rt].lazy){tree[rt<<1].lazy += tree[rt].lazy;tree[rt<<1|1].lazy += tree[rt].lazy;tree[rt<<1].max_exp += k * tree[rt].lazy;tree[rt<<1|1].max_exp += k * tree[rt].lazy;tree[rt].lazy = 0;} }void update(int rt,int l,int r,int val) {if(tree[rt].l == tree[rt].r){tree[rt].max_exp += tree[rt].rank * val;if(tree[rt].max_exp >= exprience[tree[rt].rank+1] && tree[rt].rank < k)tree[rt].rank++;if(tree[rt].rank >= k) {tree[rt].cover = 1;tree[rt].rank = k;}return;}if(tree[rt].cover && l <= tree[rt].l && tree[rt].r <= r){tree[rt<<1].cover = tree[rt<<1|1].cover = 1;tree[rt].lazy += val;tree[rt].max_exp += k * val;return;}PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;if(l <= mid) update(rt<<1,l,r,val);if(mid < r) update(rt<<1|1,l,r,val);if(tree[rt<<1].cover && tree[rt<<1|1].cover)tree[rt].cover = 1;tree[rt].max_exp = max(tree[rt<<1].max_exp,tree[rt<<1|1].max_exp); }int query(int rt,int l,int r) {if(l <= tree[rt].l && tree[rt].r <= r)return tree[rt].max_exp;PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;int ans = 0;if(l <= mid) ans = max(ans,query(rt<<1,l,r));if(mid < r) ans = max(ans,query(rt<<1|1,l,r));return ans; }int main() {int t,cas = 1,a,b,c;char str[2];scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&k,&m);for(int i = 2; i <= k; i++)scanf("%d",&exprience[i]);build(1,1,n);printf("Case %d:\n",cas++);while(m--){getchar();scanf("%s",str);if(str[0] == 'W'){scanf("%d%d%d",&a,&b,&c);update(1,a,b,c);}else{scanf("%d%d",&a,&b);printf("%d\n",query(1,a,b));}}}return 0; }

這個是看懂了別人的思路打的代碼:

#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 10005; struct Segment {int l,r;int max_exp,dis_min,rank;int lazy; }tree[maxn<<2]; int n,k,m,exprience[15];void build(int rt,int l,int r) {tree[rt].l = l, tree[rt].r = r;tree[rt].rank = 1;tree[rt].dis_min = exprience[2];tree[rt].max_exp = tree[rt].lazy = 0;if(l == r) return;int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); }void PushUp(int rt) {tree[rt].max_exp = max(tree[rt<<1].max_exp,tree[rt<<1|1].max_exp);tree[rt].dis_min = min(tree[rt<<1].dis_min,tree[rt<<1|1].dis_min);tree[rt].rank = max(tree[rt<<1].rank,tree[rt<<1|1].rank); }void PushDown(int rt) {if(tree[rt].lazy){tree[rt<<1].lazy += tree[rt].lazy;tree[rt<<1|1].lazy += tree[rt].lazy;tree[rt<<1].max_exp += tree[rt<<1].rank * tree[rt].lazy;tree[rt<<1|1].max_exp += tree[rt<<1|1].rank * tree[rt].lazy;tree[rt<<1].dis_min -= tree[rt].lazy;tree[rt<<1|1].dis_min -= tree[rt].lazy;tree[rt].lazy = 0;} }void update(int rt,int l,int r,int val) {if(l <= tree[rt].l && tree[rt].r <= r){if(tree[rt].dis_min > val) //區間內無英雄升級{tree[rt].lazy += val;tree[rt].max_exp += tree[rt].rank * val;tree[rt].dis_min -= val;return;}else if(tree[rt].l == tree[rt].r){tree[rt].max_exp += tree[rt].rank * val;while(tree[rt].max_exp >= exprience[tree[rt].rank + 1])tree[rt].rank++;tree[rt].dis_min = (exprience[tree[rt].rank + 1] - tree[rt].max_exp) / tree[rt].rank + ((exprience[tree[rt].rank + 1] - tree[rt].max_exp) % tree[rt].rank != 0);return;}}PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;if(l <= mid) update(rt<<1,l,r,val);if(mid < r) update(rt<<1|1,l,r,val);PushUp(rt); }int query(int rt,int l,int r) {if(l <= tree[rt].l && tree[rt].r <= r)return tree[rt].max_exp;PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;int ans = 0;if(l <= mid) ans = max(ans,query(rt<<1,l,r));if(mid < r) ans = max(ans,query(rt<<1|1,l,r));return ans; }int main() {int t,cas = 1,a,b,c;char str[2];scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&k,&m);for(int i = 2; i <= k; i++)scanf("%d",&exprience[i]);exprience[k+1] = 1 << 30;build(1,1,n);printf("Case %d:\n",cas++);while(m--){getchar();scanf("%s",str);if(str[0] == 'W'){scanf("%d%d%d",&a,&b,&c);update(1,a,b,c);}else{scanf("%d%d",&a,&b);printf("%d\n",query(1,a,b));}}printf("\n");}return 0; }

總結

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

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