設dp[i] 表示第i個城市到根節點的最小花費
dp[i]=min
這是o(n^2)的
這個式子可以斜率優化
dp[i]+dis[j]*p[i]=dis[i]*p[i]+q[i]+dp[j]
就是一條斜率為p[i]的直線,截(dis[j],dp[j])的最小截距
在根往下走的過程中,斜率單調遞增
這就體現了 為什麼題目中說「i號城市是j號城市的某個祖先,那麼一定存在pi<=pj」
我們按dfs序dp
現在唯一的問題就是如何得到 乙個點到根節點路徑上的單調佇列
只需要考慮如何去除兄弟節點的子樹對單調佇列的影響
即在乙個節點退出dfs時,將單調佇列恢復為這個節點開始dfs的情況
頭指標只是不斷的+1,沒有涉及到單調佇列中元素的修改,所以記錄下頭指標在哪個位置即可
尾指標涉及到元素的替換,但是它只會替換乙個元素,所以記錄下尾指標的位置,以及被當前點替換的元素是誰
當節點退出dfs時,恢復記錄的這三個值即可
這樣的話,乙個節點多次出隊入隊,時間複雜度就不是o(n)了
所以二分出隊位置,時間複雜度為o(nlogn)
樸素的dp:
#include#includeview code#include
using
namespace
std;
#define n 1000001typedef
long
long
ll;int
p[n],q[n];
int front[n],to[n<<1],nxt[n<<1],val[n<<1
],tot;
intfa[n];
ll dis[n];
intt;
ll mi[n];
void read(int &x)
}void add(int u,int v,int
w)void dfs(int x,intf)
dfs(to[i],x);
}}int
main()
dfs(
1,0);
for(int i=2;i<=n;++i) cout
;}
斜率優化,暴力出隊:
#include#includeview codeusing
namespace
std;
#define n 1000001typedef
long
long
ll;int
front[n],nxt[n],to[n],tot,val[n];
intp[n],q[n];
intq[n],head,tail;
ll dis[n];
ll dp[n];
void read(int &x)
}void add(int u,int v,int
w)inline
double x(int i,int j)
inline
double y(int i,int j)
void dfs(int
x)int
main()
for(int i=front[1];i;i=nxt[i])
for(int i=2;i<=n;++i) cout
;}
斜率優化,二分出隊
#include#includeview codeusing
namespace
std;
#define n 1000001typedef
long
long
ll;int
front[n],nxt[n],to[n],tot,val[n];
intp[n],q[n];
intq[n],head,tail;
ll dis[n];
ll dp[n];
void read(int &x)
}void add(int u,int v,int
w)inline
double x(int i,int j)
inline
double y(int i,int j)
void dfs(int
x)
if(tmp!=-1) head=tmp;
else head=tail-1
;
int j=q[head];
dp[x]=(dis[x]-dis[j])*p[x]+dp[j]+q[x];
l=head,r=tail-2,tmp=-1
;
while(l<=r)
if(tmp!=-1) tail=tmp+2
;
else tail=head+1
;
int rr=q[tail];
q[tail++]=x;
for(int i=front[x];i;i=nxt[i])
dis[to[i]]=dis[x]+val[i],dfs(to[i]);
head=now_h; q[tail-1]=rr; tail=now_t;
}int
main()
for(int i=front[1];i;i=nxt[i])
for(int i=2;i<=n;++i) cout
;}
洛谷P3948 資料結構 題解
題目傳送 感覺這道題秀了我一地的智商。審題沒審好,沒確定帶修改的操作中詢問的次數 1000,且max和min都是事先給好 不變的。想了半天線段樹 分塊,卻忘了最基礎的暴力。寫不出題時先寫暴力。離線部分 顯然不能暴力處理詢問了,但是沒有修改,又是區間詢問個數,自然要想到字首和優化了。設sum i 為前...
洛谷P3377 (資料結構 左偏樹)
題意 合併堆及刪除堆中最小元素。思路 採用一般的二叉堆可以實現刪除操作,但是要合併的話就會爆,因此引進了左偏樹這個資料結構,可在logn時間內實現合併操作。左偏樹的性質 1.堆的性質 2.左子節點的距離大於右子節點的距離 正是利用這些性質實現堆的快速合併。如下 其中並查集的路徑壓縮會破壞掉樹的結構,...
洛谷 P3948 資料結構 (差分陣列)
直接差分陣列搞一搞就ok了。因為前面的查詢和修改摻雜在一起的詢問很少,所以對於那些詢問我們暴力去查詢就ok。在final詢問之前求乙個符合要求的字首和就可以o 1 輸出了。include using namespace std const int maxn 8e4 5 typedef long lo...