bzoj千题计划276:bzoj4515: [Sdoi2016]游戏
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=123456789123456789; long long n,m; long long front[N],nxt[N<<1],to[N<<1],val[N<<1],tot; long long fa[N],siz[N]; LL dep[N]; long long bl[N]; long long id[N],tim,dy[N]; LL mi[N<<2]; LL mi_dep[N<<2],mx_dep[N<<2]; int who[N<<2]; LL tagA[N<<2],tagB[N<<2]; long long L[N<<2],R[N<<2]; bool have[N<<2]; LL A,B; LL ans; bool zero; void read(long long &x) { x=0; long long f=1; char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; 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=1;i<n;++i) { read(u); read(v); read(w); add(u,v,w); } } void dfs1(long long x) { siz[x]=1; 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=0; 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>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); mi_dep[k]=min(mi_dep[k<<1],mi_dep[k<<1|1]); mx_dep[k]=max(mx_dep[k<<1],mx_dep[k<<1|1]); if(mx_dep[k]==mx_dep[k<<1]) who[k]=who[k<<1]; else who[k]=who[k<<1|1]; } double get_point(LL k1,LL b1,LL k2,LL b2) { if(k1==k2) { zero=true; return 0; } return 1.0*(b2-b1)/(k1-k2); } void unionn_tag(long long k,LL tA,LL tB) { if(!have[k]) { LL v; if(tA>0) 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>0) 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>0) 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]>>1; if(foot<=dep[dy[mid]]) { if(v1now<=v1pre) { unionn_tag(k<<1,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<<1,tA,tB); if(v1now>v2now) swap(v1now,v2now); mi[k]=min(mi[k],v1now); } } else { if(v1now<=v1pre) { unionn_tag(k<<1|1,tA,tB); if(v1now>v2now) swap(v1now,v2now); mi[k]=min(mi[k],v1now); } else { unionn_tag(k<<1|1,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<<1,tagA[k],tagB[k]); unionn_tag(k<<1|1,tagA[k],tagB[k]); tagA[k]=tagB[k]=0; 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>>1; if(opl<=mid) change(k<<1,l,mid,opl,opr); if(opr>mid) change(k<<1|1,mid+1,r,opl,opr); mi[k]=min(mi[k<<1],mi[k<<1|1]); } void Change(long long u,long long v) { while(bl[u]!=bl[v]) { if(dep[bl[u]]<dep[bl[v]]) swap(u,v); change(1,1,n,id[bl[u]],id[u]); u=fa[bl[u]]; } if(dep[u]>dep[v]) swap(u,v); change(1,1,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>>1; if(opl<=mid) query(k<<1,l,mid,opl,opr); if(opr>mid) query(k<<1|1,mid+1,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(1,1,n,id[bl[u]],id[u]); u=fa[bl[u]]; } if(dep[u]>dep[v]) swap(u,v); query(1,1,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>=10) out(x/10); putchar(x%10+'0'); } 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==2) { ans=inf; Query(t,s); if(ans<0) 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]-2*dep[lca])*a+b; // printf("%I64d\n",(dep[s]+dep[7]-2*dep[lca])*a+b); Change(lca,t); } } } int main() { init(); dfs1(1); dfs2(1,1); //for(int i=1;i<=n;++i) printf("%d\n",bl[i]); build(1,1,n); solve(); return 0; }