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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈)

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

一棵 n 個點的有根樹,帶點權 wi。
從 s 出發,希望達到 t,每秒可以從當前點移動到某一個兒子。
有一個死亡次數,初始為 0。若在某個點 i(i != s, t) 時,死亡次數 ≤ wi,那么死亡次數自增 1,并且立刻跳回到 s。
給出 q 組 s, t,求最短時間。
n, q ≤ 3×1053 \times 10^53×105

Solution

  • 每次從點 s 出生到撞程序猿死亡跟前幾次是怎么死的并沒有關系。所以對于每次 “從點 s 出生到撞程序猿死亡” 的過程都可以貪心選最近的點早死早超生。
  • 產生一個樸素的想法:記 gi,jg_i,_jgi?,j? 為當前在 i,已死亡 j ? 1 次,再死一次所需時間。若 s, t 路徑上最大點權為 W,那么答案為 ∑i=1Wgs,i+dis(s,t)\sum _{i=1}^W g_s,_i + dis(s, t)i=1W?gs?,i?+dis(s,t)
  • 這樣設計狀態的復雜度太大,發現 g 單調并且有大量狀態相同。圖像的話大概長這樣:
  • 優化:換個角度,考慮有多少次從出生到死亡的過程需要一秒,多少次需要兩秒等等。
  • 具體來說,考慮記錄 f[i][j] 表示 i 的子樹中和 i 距離小于等于 j 的點的權值最大值。 這樣 f[i][j]?f[i][j?1] 就等于有多少次從出生到死亡需要 j 秒。
  • 那么對于一個詢問(s,t),答案就是
    ∑i=1d=dep[pos[mxval]]?dep[s](f[s][i]?f[s][i?1])?i+dis(s,t)\sum_{i=1}^{d=dep[pos[mxval]]-dep[s]}(f[s][i]-f[s][i-1])*i+dis(s,t)i=1d=dep[pos[mxval]]?dep[s]?(f[s][i]?f[s][i?1])?i+dis(s,t)
    =f[s][d]?d?∑i=1d?1f[s][i]+dis(s,t)=f[s][d]*d-\sum_{i=1}^{d-1}f[s][i]+dis(s,t)=f[s][d]?d?i=1d?1?f[s][i]+dis(s,t)
  • 所以,可以把詢問按照 s 掛在樹上,想辦法維護f,離線求解。
  • 考慮如何維護f。因為它與深度有關,所以考慮長鏈剖分。
  • 長鏈剖分完后有兩種合并鏈的方法:
  • 法一:用一個點v去更新f,是區間對一個數取max的操作,但因為f單調遞增,所以可以二分出第一個大于 v 的位置,然后區間覆蓋就可以了。這個可以用線段樹實現。(推薦按照樹剖的DFS序建一棵線段樹,然后所有操作都可以在這一棵線段樹上做。)
    時間復雜度 O((n+q)logn)O((n+q)logn)O((n+q)logn)
  • 法二:若dep[j]<dep[k]且w[j]>w[k],那么k點顯然可以不用維護了,發現刪掉類似k的點后我們就得到了一個單調棧!因此我們決定維護一個子樹內部按照深度排好序后對于 w 的單調棧。詢問直接二分就好。注意點:1.我們需要求單調棧從棧頂到棧底的前綴和,但是不好維護,所以選擇維護后綴和。2.棧的合并實際上按照任意順序時間復雜度都是O(n)O(n)O(n),但是我們需要注意空間,為省空間,我們長鏈剖分之后按照DFS序分配空間即可。
    時間復雜度 O(n+qlogn)O(n+qlogn)O(n+qlogn)
  • Code

    #include<iostream> #include<cstdio> #include<vector> using namespace std; const int N=3e5+5; struct Edge{int v,nxt;}edge[N]; int n,m,w[N],cnt,head[N]; int fa[N][25],mxw[N][25],len[N],son[N],dep[N],dfn[N],ind; struct Query{int y,id;}; vector<Query> d[N]; long long ans[N]; int L[N],R[N],tot; long long sum[N];//sum維護后綴和 struct Stack{int dep,w;}stk[N],q[N]; //用stk來記錄單調棧,是為了省空間 //按dfs序分配空間即可保證每個點對應的棧使用的stk區間無重疊部分 void addedge(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt; } void dfs1(int u){dep[u]=dep[fa[u][0]]+1;mxw[u][0]=w[fa[u][0]];for(int i=1;i<=20;i++){fa[u][i]=fa[fa[u][i-1]][i-1];mxw[u][i]=max(mxw[u][i-1],mxw[fa[u][i-1]][i-1]);}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;dfs1(v);if(len[v]>len[son[u]]) son[u]=v;}len[u]=len[son[u]]+1; } int get_mxw(int x,int y){int ret=0;for(int i=20;i>=0;i--)if(dep[fa[x][i]]>dep[y])ret=max(ret,mxw[x][i]),x=fa[x][i];return ret; } void add(int x,Stack a){//從x點的棧的左端加入新元素 //新加入元素的dep保證<=棧中元素的dep的最小值 while(L[x]<=R[x]&&stk[L[x]].w<=a.w) L[x]++;if(L[x]>R[x]){sum[--L[x]]=0;stk[L[x]]=a;} else{if(stk[L[x]].dep>a.dep){stk[--L[x]]=a;sum[L[x]]=sum[L[x]+1]+1ll*stk[L[x]+1].dep*(stk[L[x]+1].w-a.w);}} } void merge(int x,int y){//往x點的棧加入y點的棧中的元素時仍要滿足x點的棧中的元素dep值從小到大排布 tot=0;while(L[x]<=R[x]&&stk[L[x]].dep<=stk[R[y]].dep) q[++tot]=stk[L[x]++];while(tot&&L[y]<=R[y])if(q[tot].dep>=stk[R[y]].dep) add(x,q[tot--]);else add(x,stk[R[y]--]);while(tot) add(x,q[tot--]);while(L[y]<=R[y]) add(x,stk[R[y]--]); } long long query(int u,int v){int mx=get_mxw(v,u),l=L[u],r=R[u],mid;while(l<=r){mid=l+r>>1;if(stk[mid].w<mx) l=mid+1;else r=mid-1;}if(stk[L[u]].w<=mx)return 1ll*sum[L[u]]- 1ll*sum[l] + 1ll*stk[L[u]].dep*stk[L[u]].w - 1ll*dep[u]*mx - 1ll*(stk[l].w-mx)*stk[l].dep;elsereturn 1ll*mx*(stk[l].dep-dep[u]); } void dfs2(int u){dfn[u]=++ind;if(son[u]){dfs2(son[u]);L[u]=L[son[u]];R[u]=R[son[u]];}else{L[u]=ind;R[u]=ind-1;}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==son[u]) continue;dfs2(v);merge(u,v);}for(int i=0;i<d[u].size();i++){int v=d[u][i].y;int id=d[u][i].id;ans[id]=query(u,v)+dep[v]-dep[u];}add(u,(Stack){dep[u],w[u]}); } int main(){scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&w[i]);for(int i=2;i<=n;i++){scanf("%d",&fa[i][0]);addedge(fa[i][0],i);}dfs1(1);scanf("%d",&m);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);d[u].push_back((Query){v,i}); }dfs2(1);for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);return 0; }

    參考文章:
    https://vfleaking.blog.uoj.ac/blog/2292
    https://www.cnblogs.com/penth/p/9801945.html
    https://blog.csdn.net/qq_42555009/article/details/100934540
    https://blog.csdn.net/zxyoi_dreamer/article/details/101705010
    https://blog.csdn.net/Mr_wuyongcong/article/details/111996460

    總結

    以上是生活随笔為你收集整理的UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 特级毛片爽www免费版 | 欧美黄色短片 | 久色国产 | 波多野结衣乳巨码无在线 | 日韩国产高清在线 | 校园春色在线观看 | 娇妻之欲海泛舟无弹窗笔趣阁 | 蜜桃视频欧美 | 精品一区二区三区四区五区 | 美女av免费在线观看 | 国产短视频一区 | 国产在线久久久 | 日韩a级大片 | 丁香婷婷激情 | 三级a毛片 | 日本精品影院 | 日本人妻一区 | 久久国产精品视频 | 美女视频黄色免费 | 欧美激情精品久久久久久变态 | 精品久久久久一区 | 大尺度床戏视频 | 亚洲国产精品综合久久久 | 不卡影院一区二区 | 欧洲亚洲一区二区三区 | 色婷婷a | 91久久久久国产一区二区 | 一级特黄bbbbb免费观看 | 国产免费av一区二区三区 | 亚洲第一天堂久久 | 免费在线日韩 | 日本午夜精华 | 成人一区二区三区 | 免费看国产视频 | 黄色69视频 | 中文字幕在线视频精品 | 精品国产三级片在线观看 | 裸体喂奶一级裸片 | 欧美成人高潮一二区在线看 | 自由成熟xxxx色视频 | 超碰日日干| 青青草成人在线 | 亚洲福利一区二区三区 | 国产情侣自拍一区 | 亚洲成人一区二区 | 有码视频在线观看 | 蜜桃免费在线视频 | 国产一区二区免费电影 | 密臀av在线播放 | 激情综合网五月天 | 在线黄色免费网站 | 国产超碰 | 精品一区二区在线看 | 9久久精品 | 国产欧美日本在线 | 91一区二区三区在线观看 | 久久久久久逼 | 亚洲成人av网址 | 欧美色图1 | 91高潮大合集爽到抽搐 | 91九色国产| 欧美成人性色 | 亚洲精品国产手机 | 在线免费观看污网站 | 四虎精品一区二区 | 国自产拍偷拍精品啪啪一区二区 | 中文字幕亚洲高清 | 91美女网站 | 国产在线中文字幕 | 韩国精品在线 | 国产又猛又黄 | 人妻无码一区二区三区久久 | 欧美性受xxxx白人性爽 | 国产一区=区 | 第色| 欧美日韩在线观看一区 | 亚洲人成小说 | 18久久久| 日韩和欧美的一区二区 | 男人扒女人添高潮视频 | 麻豆chinese新婚xxx | 国产一级爱c视频 | 欧美69久成人做爰视频 | 极品少妇一区二区三区 | 国产美女永久无遮挡 | 一级片中文 | 青春草在线视频免费观看 | 欧美碰碰碰 | 欧美老熟妇一区二区三区 | 嫩草视频在线观看免费 | 欧美成人性生活 | 色av网站| bangbros性欧美18 | 91们嫩草伦理| 亚洲专区中文字幕 | 欧美一区高清 | 免费观看黄色av | 青草视频免费观看 | 亚洲区视频 |