http://www.lydsy.com/JudgeOnline/problem.php?id=4515
把lca带进式子,得到新的式子
然后就是 维护树上一次函数取min
一个调了一下午的错误:
当一条线段完全在另一条线段之下时,用下面的完全覆盖上面的
判断条件为 两线段在范围内没有交点
然后若 新的线段的某一个端点<原来线段的对应的一个端点,就覆盖
错误的写法:
判断的时候 把两条线段在端点处相等也加了进去
即判断条件为 两线段在范围内没有交点 或 交点 在线段端点出
那么 若 新的线段的某一个端点<=原来线段的对应的一个端点,就覆盖
不对!!
因为交点在一个端点, 某一个端点<=原来线段的对应的一个端点,这个某一个交点 如果恰好是交点
那么这两条线段谁覆盖谁都有可能
所以应该是 若新线段有一个端点<原线段的对应端点,就覆盖
因为 一直没有找出上面的错误,而且是后10个点WA,所以一气之下把所有的int替换成了long long。。。。
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 100001 #define min(x,y) ((x)<(y) ? (x) : (y)) typedef long long LL; const LL inf=; long long n,m; long long front[N],nxt[N<<],to[N<<],val[N<<],tot; long long fa[N],siz[N];
LL dep[N]; long long bl[N];
long long id[N],tim,dy[N]; LL mi[N<<];
LL mi_dep[N<<],mx_dep[N<<];
int who[N<<];
LL tagA[N<<],tagB[N<<];
long long L[N<<],R[N<<];
bool have[N<<]; LL A,B; LL ans; bool zero; void read(long long &x)
{
x=; long long f=; char c=getchar();
while(!isdigit(c)){ if(c=='-') f=-; c=getchar(); }
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
x*=f;
} void add(long long u,long long v,long long w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w;
} void init()
{
read(n); read(m);
long long u,v,w;
for(long long i=;i<n;++i)
{
read(u); read(v); read(w);
add(u,v,w);
}
} void dfs1(long long x)
{
siz[x]=;
for(long long i=front[x];i;i=nxt[i])
if(to[i]!=fa[x])
{
fa[to[i]]=x;
dep[to[i]]=dep[x]+val[i];
dfs1(to[i]);
siz[x]+=siz[to[i]];
}
} void dfs2(long long x,long long top)
{
bl[x]=top;
id[x]=++tim;
dy[tim]=x;
long long y=;
for(long long i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
if(!y) return;
dfs2(y,top);
for(long long i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && to[i]!=y) dfs2(to[i],to[i]);
} void build(long long k,long long l,long long r)
{
mi[k]=inf;
L[k]=l;
R[k]=r;
if(l==r)
{
mi_dep[k]=mx_dep[k]=dep[dy[l]];
who[k]=dy[l];
return;
}
long long mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
mi_dep[k]=min(mi_dep[k<<],mi_dep[k<<|]);
mx_dep[k]=max(mx_dep[k<<],mx_dep[k<<|]);
if(mx_dep[k]==mx_dep[k<<]) who[k]=who[k<<];
else who[k]=who[k<<|];
} double get_point(LL k1,LL b1,LL k2,LL b2)
{
if(k1==k2)
{
zero=true;
return ;
}
return 1.0*(b2-b1)/(k1-k2);
} void unionn_tag(long long k,LL tA,LL tB)
{
if(!have[k])
{
LL v;
if(tA>) v=tA*mi_dep[k]+tB;
else v=tA*mx_dep[k]+tB;
int kk=who[k];
if(v<mi[k]) mi[k]=v;
tagA[k]=tA;
tagB[k]=tB;
have[k]=true;
return;
}
if(!(R[k]-L[k]))
{
if(tA>) mi[k]=min(mi[k],tA*mi_dep[k]+tB);
else mi[k]=min(mi[k],tA*mx_dep[k]+tB);
return;
}
zero=false;
double foot=get_point(tA,tB,tagA[k],tagB[k]);
LL v1now=tA*dep[dy[R[k]]]+tB;
LL v2now=tA*dep[dy[L[k]]]+tB;
LL v1pre=tagA[k]*dep[dy[R[k]]]+tagB[k];
LL v2pre=tagA[k]*dep[dy[L[k]]]+tagB[k];
if(zero)
{
if(tB<tagB[k])
{
LL v;
if(tA>) v=tA*mi_dep[k]+tB;
else v=tA*mx_dep[k]+tB;
mi[k]=min(mi[k],v);
tagA[k]=tA;
tagB[k]=tB;
}
return;
}
if(foot<=dep[dy[L[k]]] || foot>=dep[dy[R[k]]])
{
if(v2now<v2pre || v1now<v1pre)
{
tagA[k]=tA;
tagB[k]=tB;
if(v1now>v2now) swap(v1now,v2now);
mi[k]=min(mi[k],v1now);
}
return;
}
long long mid=L[k]+R[k]>>;
if(foot<=dep[dy[mid]])
{
if(v1now<=v1pre)
{
unionn_tag(k<<,tagA[k],tagB[k]);
tagA[k]=tA;
tagB[k]=tB;
if(v1now>v2now) swap(v1now,v2now);
mi[k]=min(mi[k],v1now);
}
else
{
unionn_tag(k<<,tA,tB);
if(v1now>v2now) swap(v1now,v2now);
mi[k]=min(mi[k],v1now);
}
}
else
{
if(v1now<=v1pre)
{
unionn_tag(k<<|,tA,tB);
if(v1now>v2now) swap(v1now,v2now);
mi[k]=min(mi[k],v1now);
}
else
{
unionn_tag(k<<|,tagA[k],tagB[k]);
tagA[k]=tA;
tagB[k]=tB;
if(v1now>v2now) swap(v1now,v2now);
mi[k]=min(mi[k],v1now);
}
}
} void down(long long k)
{
if(!have[k]) return;
unionn_tag(k<<,tagA[k],tagB[k]);
unionn_tag(k<<|,tagA[k],tagB[k]);
tagA[k]=tagB[k]=;
have[k]=false;
} void change(long long k,long long l,long long r,long long opl,long long opr)
{
if(l>=opl && r<=opr)
{
unionn_tag(k,A,B);
return;
}
down(k);
long long mid=l+r>>;
if(opl<=mid) change(k<<,l,mid,opl,opr);
if(opr>mid) change(k<<|,mid+,r,opl,opr);
mi[k]=min(mi[k<<],mi[k<<|]);
} void Change(long long u,long long v)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
change(,,n,id[bl[u]],id[u]);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
change(,,n,id[u],id[v]);
} void query(long long k,long long l,long long r,long long opl,long long opr)
{
if(l>=opl && r<=opr)
{
ans=min(ans,mi[k]);
return;
}
down(k);
long long mid=l+r>>;
if(opl<=mid) query(k<<,l,mid,opl,opr);
if(opr>mid) query(k<<|,mid+,r,opl,opr);
} void Query(long long u,long long v)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
query(,,n,id[bl[u]],id[u]);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
query(,,n,id[u],id[v]);
} long long get_lca(long long u,long long v)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
u=fa[bl[u]];
}
return dep[u]<dep[v] ? u : v;
} void out(LL x)
{
if(x>=) out(x/);
putchar(x%+'');
} void solve()
{
long long ty,s,t,a,b;
long long lca;
while(m--)
{
read(ty); read(s); read(t);
lca=get_lca(s,t);
if(ty==)
{
ans=inf;
Query(t,s);
if(ans<) putchar('-'),ans=-ans;
out(ans);
putchar('\n');
}
else
{
read(a); read(b);
lca=get_lca(s,t);
A=-a; B=a*dep[s]+b;
// printf("%I64d\n",(dep[s]-dep[7])*a+b);
Change(lca,s);
A=a; B=(dep[s]-*dep[lca])*a+b;
// printf("%I64d\n",(dep[s]+dep[7]-2*dep[lca])*a+b);
Change(lca,t);
}
}
} int main()
{
init();
dfs1();
dfs2(,);
//for(int i=1;i<=n;++i) printf("%d\n",bl[i]);
build(,,n);
solve();
return ;
}