Luogu2680 運輸計劃
阿新 • • 發佈:2020-09-11
https://www.luogu.com.cn/problem/P2680
樹鏈剖分
我們對每條邊\(i\)單獨考慮,那麼設\(v_i\)為這條邊的長度,經過它的路徑長度集合為\(S\),未經過它的路徑長度集合為\(T\)
\[ans_i=\max \begin{cases} S_{max}-v_i \\ T_{max} \end{cases} \\ Ans=\min ans_i \]
對於\(S_{max}\),我們直接對於一條長度為\(L\)的路徑,該路徑上的邊都對\(L\)取\(\max\),用樹鏈剖分很容易處理
對於\(T_{max}\),對於一條長度為\(L\)的路徑,不在該路徑上的邊都對\(L\)
計算路徑長度\(L\),用了帶按秩合併優化的\(Tarjan\)求\(LCA\)
時間複雜度:\(O(n \log^2 n)\)
掛點\(1.\)線段樹忘開四倍空間。。。
掛點\(2.\)一開始\(T\)了,結果發現是它的鍋
#define Rmin(x,y) ((x<y)?x:y) #define Rmax(x,y) ((x>y)?x:y)
在下面的程式碼的線段樹中,由於\(define\),需要先線段樹搜尋一次,與\(y\)比較,然後返回值時再搜尋一次,時間爆炸
經驗:下次寫什麼函式之類的再也不用\(define\)了\(QAQ\)
錯誤程式碼:
#define Rmin(x,y) ((x<y)?x:y) #define Rmax(x,y) ((x>y)?x:y) #define ls (p << 1) #define rs ((p << 1) | 1) #define lc ls,l,mid #define rc rs,mid+1,r struct Segment_Tree { int tr[N]; void modify(int p,int l,int r,int x,int y,int z) { if (l==x && r==y) { tr[p]=Rmax(tr[p],z); return; } int mid=(l+r) >> 1; if (y<=mid) modify(lc,x,y,z); else if (x>mid) modify(rc,x,y,z); else { modify(lc,x,mid,z); modify(rc,mid+1,y,z); } } int query(int p,int l,int r,int x) { if (l==r) return tr[p]; int mid=(l+r) >> 1; if (x<=mid) return Rmax(tr[p],query(lc,x)); else return Rmax(tr[p],query(rc,x)); } }t1,t2;
完整\(AC\)程式碼
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define N 300005
using namespace std;
int n,m,x,y,z,tot=0,fr[N],nxt[N << 1],d1[N << 1],d2[N << 1];
int cnt=0,f[N],dep[N],son[N],sz[N],dfn[N],t[N],len[N];
int ans,ft[N],rf[N],rz[N],rg[N],lca[N];
struct node
{
int x,y;
node (int xx=0,int yy=0)
{
x=xx,y=yy;
}
bool operator < (const node &b) const
{
return x<b.x;
}
}q[N],g[N];
vector<node>e[N];
int read()
{
int S=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
{
S=S*10+c-'0';
c=getchar();
}
return S;
}
void write(int x)
{
if (x>9)
write(x/10);
putchar(x%10+'0');
}
void add(int x,int y,int z)
{
tot++;
d1[tot]=y;
d2[tot]=z;
nxt[tot]=fr[x];
fr[x]=tot;
}
int getf(int x)
{
return (x==rf[x])?x:(rf[x]=getf(rf[x]));
}
void dfs1(int u)
{
rf[u]=u;
rg[u]=u;
rz[u]=1;
int mx=0;
sz[u]=1;
for (int i=fr[u];i;i=nxt[i])
{
int v=d1[i];
if (v==f[u])
continue;
f[v]=u;
dep[v]=dep[u]+1;
len[v]=len[u]+d2[i];
ft[v]=d2[i];
dfs1(v);
sz[u]+=sz[v];
if (sz[v]>mx)
{
mx=sz[v];
son[u]=v;
}
int fu=getf(u);
int fv=getf(v);
if (rz[fv]<=rz[fu])
{
rz[fu]+=rz[fv];
rf[fv]=fu;
} else
{
rf[fu]=fv;
rz[fv]+=rz[fu];
rg[fv]=u;
}
}
for (vector<node> :: iterator it=e[u].begin();it!=e[u].end();++it)
if (rf[it->x])
lca[it->y]=rg[getf(it->x)];
}
void dfs2(int u,int tt)
{
dfn[u]=++cnt;
t[u]=tt;
if (!son[u])
return;
dfs2(son[u],tt);
for (int i=fr[u];i;i=nxt[i])
{
int v=d1[i];
if (v==f[u] || v==son[u])
continue;
dfs2(v,v);
}
}
#define ls (p << 1)
#define rs ((p << 1) | 1)
#define lc ls,l,mid
#define rc rs,mid+1,r
struct Segment_Tree
{
int tr[N << 2];
void modify(int p,int l,int r,int x,int y,int z)
{
if (l==x && r==y)
{
tr[p]=max(tr[p],z);
return;
}
int mid=(l+r) >> 1;
if (y<=mid)
modify(lc,x,y,z); else
if (x>mid)
modify(rc,x,y,z); else
{
modify(lc,x,mid,z);
modify(rc,mid+1,y,z);
}
}
int query(int p,int l,int r,int x)
{
if (l==r)
return tr[p];
int mid=(l+r) >> 1;
if (x<=mid)
return max(tr[p],query(lc,x)); else
return max(tr[p],query(rc,x));
}
}t1,t2;
void Achange(int x,int y,int z)
{
int g0=0;
while (t[x]!=t[y])
{
if (dep[t[x]]<dep[t[y]])
swap(x,y);
t1.modify(1,1,n,dfn[t[x]],dfn[x],z);
g[++g0]=node(dfn[t[x]],dfn[x]);
x=f[t[x]];
}
if (x!=y)
{
if (dep[x]>dep[y])
swap(x,y);
t1.modify(1,1,n,dfn[son[x]],dfn[y],z);
g[++g0]=node(dfn[son[x]],dfn[y]);
}
sort(g+1,g+g0+1);
int o=1;
for (int i=1;i<=g0;o=g[i].y+1,i++)
{
if (g[i].x==o)
continue;
t2.modify(1,1,n,o,g[i].x-1,z);
}
if (o<=n)
t2.modify(1,1,n,o,n,z);
}
int main()
{
n=read(),m=read();
for (int i=1;i<n;i++)
{
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
for (int i=1;i<=m;i++)
q[i].x=read(),q[i].y=read(),e[q[i].x].push_back(node(q[i].y,i)),e[q[i].y].push_back(node(q[i].x,i));
dfs1(1);
dfs2(1,1);
for (int i=1;i<=m;i++)
{
int x=q[i].x,y=q[i].y,z=lca[i];
int l=len[x]+len[y]-(len[z] << 1);
Achange(x,y,l);
}
ans=1000000007;
for (int i=2;i<=n;i++)
{
int e=t1.query(1,1,n,dfn[i])-ft[i];
int o=t2.query(1,1,n,dfn[i]);
ans=min(ans,max(e,o));
}
write(ans),putchar('\n');
return 0;
}