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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Codeforces 671D. Roads in Yusland(树形DP+线段树)

發布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces 671D. Roads in Yusland(树形DP+线段树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  調了半天居然還能是線段樹寫錯了,藥丸

  這題大概是類似一個樹形DP的東西。設$dp[i]$為修完i這棵子樹的最小代價,假設當前點為$x$,但是轉移的時候我們不知道子節點到底有沒有一條越過$x$的路。如果我們枚舉每條路去轉移,會發現這條路沿線上的其他子樹的答案難以統計,那怎么辦呢,我們可以讓這條路向上回溯的時候順便記錄一下,于是有$val[i]$表示必修i這條路,并且修完當前子樹的最小代價。

  則有轉移$dp[x]=min(val[j])$,且$j$這條路必須覆蓋$x$。

  $val[i]=(\sum dp[son])-dp[sonx]+val[i]$,且$i$這條路必須覆蓋$sonx$。

  轉移用線段樹來維護就好,至于怎么判斷某條路是否覆蓋兩個點,只要遞歸到某條路的起點的時候把$val[i]$改為$(\sum dp[son])+cost[i]$,遞歸到某條路終點的時候把$val[i]$改為$inf$就好了。

#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=500010; const ll inf=1e15; struct poi{ll sum, delta;}tree[maxn<<2]; struct tjm{int too, pre;}e[maxn<<1], e2[maxn<<1], e3[maxn<<1]; struct qaq{int x, y, cost, pos;}q[maxn]; ll dp[maxn]; int n, m, x, y, tot, tot2, tot3, tott, l[maxn], r[maxn], last[maxn], last2[maxn], last3[maxn]; inline void read(int &k) {int f=1; k=0; char c=getchar();while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();k*=f; } inline void add(int x, int y){e[++tot]=(tjm){y, last[x]}; last[x]=tot;} inline void add2(int x, int y){e2[++tot2]=(tjm){y, last2[x]}; last2[x]=tot2;} inline void add3(int x, int y){e3[++tot3]=(tjm){y, last3[x]}; last3[x]=tot3;} inline void up(int x) {tree[x].sum=min(tree[x<<1].sum, tree[x<<1|1].sum);} inline void addone(int x, int l, int r, ll delta) {tree[x].delta=min(inf, tree[x].delta+delta);tree[x].sum=min(inf, tree[x].sum+delta); } inline void down(int x, int l, int r) {int mid=(l+r)>>1;addone(x<<1, l, mid, tree[x].delta);addone(x<<1|1, mid+1, r, tree[x].delta);tree[x].delta=0; } void build(int x, int l, int r) {if(l==r) {tree[x].sum=inf; return;}int mid=(l+r)>>1;build(x<<1, l, mid); build(x<<1|1, mid+1, r);up(x); } void update(int x, int l, int r, int cx, ll delta) {if(l==r) {tree[x].sum=delta; return;}down(x, l, r);int mid=(l+r)>>1;if(cx<=mid) update(x<<1, l, mid, cx, delta);else update(x<<1|1, mid+1, r, cx, delta);up(x); } void change(int x, int l, int r, int cl, int cr, ll delta) {if(cl>cr) return;if(cl<=l && r<=cr) {addone(x, l, r, delta); return;}down(x, l, r);int mid=(l+r)>>1;if(cl<=mid) change(x<<1, l, mid, cl, cr, delta);if(cr>mid) change(x<<1|1, mid+1, r, cl, cr, delta);up(x); } ll query(int x, int l, int r, int cl, int cr) {if(cl>cr) return inf;if(cl<=l && r<=cr) return tree[x].sum;down(x, l, r);int mid=(l+r)>>1; ll ans=inf;if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);if(cr>mid) ans=min(ans, query(x<<1|1, mid+1, r, cl, cr));return ans; } void dfs1(int x, int fa) {l[x]=++tott;for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) dfs1(too, x);r[x]=tott; } inline int find(int x) {int l=1, r=m+1;while(l<r){int mid=(l+r)>>1;if(q[mid].pos>=x) r=mid;else l=mid+1; }return l; } void dfs2(int x, int fa) {ll sum=0;for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) dfs2(too, x), sum=min(inf, sum+dp[too]);if(x==1) {dp[1]=sum; return;}for(int i=last2[x];i;i=e2[i].pre) update(1, 1, m, e2[i].too, min(inf, q[e2[i].too].cost+sum));for(int i=last3[x];i;i=e3[i].pre) update(1, 1, m, e3[i].too, inf);for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) change(1, 1, m, find(l[too]), find(r[too]+1)-1, sum-dp[too]);dp[x]=query(1, 1, m, find(l[x]), find(r[x]+1)-1); } inline bool cmp(qaq a, qaq b){return a.pos<b.pos;} int main() {read(n); read(m); build(1, 1, m);for(int i=1;i<n;i++) read(x), read(y), add(x, y), add(y, x);dfs1(1, 0); for(int i=1;i<=m;i++) read(q[i].x), read(q[i].y), read(q[i].cost), q[i].pos=l[q[i].x];sort(q+1, q+1+m, cmp); q[m+1].pos=n+1;for(int i=1;i<=m;i++) add2(q[i].x, i), add3(q[i].y, i);dfs2(1, 0);if(dp[1]>=inf) return puts("-1"), 0;printf("%lld\n", dp[1]); } View Code

轉載于:https://www.cnblogs.com/Sakits/p/8085598.html

總結

以上是生活随笔為你收集整理的Codeforces 671D. Roads in Yusland(树形DP+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。

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