题目描述
SOL 奇奇怪怪的码农题。
我们考虑是一颗树怎么做,我们发现我们可以离线做,把车的限速排序,依次处理,我们首先是树剖,把边分成两类,最高速度小于车速和大于车速的。每次做之前先把最高速度小于当前车速的加到另一类。强行树剖维护。至于多出来的那一条边,我们记其练了A , B,记我们原来的始末位置为X,Y,所以我们有3条可行的路径,X-Y,X-a-b-Y,X-b-a-Y。取min即可。
#pragma GCC optimize("-O2") #include<bits/stdc++.h> #define sight(c) (‘0‘<=c&&c<=‘9‘) #define eho(x) for (int i=head[x];i;i=net[i]) #define LL long long #define L(x) (x&-x) #define inf (1<<26) //#define int long long #define LL long long #define N 100007 #define db long double using namespace std; int VV,n,fall[N<<1],net[N<<1],head[N],tot,siz[N],son[N],usd[N],be[N], ed[N],f[N],tim,top[N],dep[N],m,q,v[N],w[N],id,Top; db HCHO,Ans,ans[N]; bool U[N]; inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } inline void read(LL &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } struct Node { int a,b,v,id; inline bool operator <(const Node &a)const{return v<a.v;} }T[N]; struct edge { int a,b,l,x; bool operator <(const edge& a)const{return x>a.x;} }L[N]; struct Tree { db a[N]; inline void add(int x,db dla){for(;x<N;x+=L(x))a[x]+=dla;} inline db query(int x){db o;for(o=0;x;x-=L(x))o+=a[x];return o;} }A1,A2; inline void add(int x,int y){fall[++tot]=y; net[tot]=head[x]; head[x]=tot;} void dfs(int x,int fa){ U[x]=1; siz[x]=1; son[x]=0; dep[x]=dep[fa]+1; eho(x) if (fall[i]^fa&&!U[fall[i]]) { usd[i>>1]=fall[i]; ed[fall[i]]=i>>1; dfs(fall[i],x); siz[x]+=siz[fall[i]]; siz[fall[i]]<siz[son[x]]?:son[x]=fall[i]; } } void dfs2(int x,int fa,int op){ // t[++tim]=x; be[x]=++tim; top[x]=op; f[x]=fa; if (son[x]) dfs2(son[x],x,op); eho(x) if (fall[i]^fa&&fall[i]^son[x]&& (i>>1)^id) dfs2(fall[i],x,fall[i]); } inline db min(db x,db y){return x<y?x:y;} db ask(int x,int y) { Ans=0; while (top[x]^top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); Ans+=(A1.query(be[x])-A1.query(be[top[x]]-1))/VV+A2.query(be[x])-A2.query(be[top[x]]-1); x=f[top[x]]; } if (dep[x]>dep[y]) swap(x,y); Ans+=(A1.query(be[y])-A1.query(be[x]))/VV+A2.query(be[y])-A2.query(be[x]); return Ans; } signed main() { read(n);read(m);read(q); add(0,0); for (int i=1;i<=n;i++) read(L[i].a),read(L[i].b),read(L[i].l),read(L[i].x); sort(L+1,L+n+1); for (int i=1;i<=n;i++) add(L[i].a,L[i].b),add(L[i].b,L[i].a); for (int i=1;i<=m;i++) read(v[i]),read(w[i]); v[0]=inf; dfs(1,0); for (int i=1;i<=n;i++) if (!usd[i]) {id=i;break;} for (int i=1;i<=q;i++) read(T[i].a),read(T[i].b),read(T[i].v),T[i].id=i; dfs2(1,0,1); #define top Top sort(T+1,T+q+1); top=1; for (int i=1;i<=n;i++) if (usd[i]) A1.add(be[usd[i]],(LL)L[i].l*w[L[i].x]); for (int i=1;i<=q;i++) { VV=T[i].v; HCHO=T[i].v>v[L[id].x]?(LL)L[id].l*w[L[id].x]*1.0/v[L[id].x]:(LL)L[id].l*w[L[id].x]*1.0/T[i].v; while (T[i].v>=v[L[top].x]) { if (usd[top]) { A1.add(be[usd[top]],(db)-1.0*L[top].l*w[L[top].x]); A2.add(be[usd[top]],(LL)L[top].l*w[L[top].x]*1.0/v[L[top].x]);} top++;} ans[T[i].id]=min(ask(T[i].a,T[i].b), min(ask(T[i].a,L[id].a)+ask(T[i].b,L[id].b), ask(T[i].a,L[id].b)+ask(T[i].b,L[id].a))+HCHO ); } for (int i=1;i<=q;i++) printf("%.10Lf\n",ans[i]);return 0; }