bzoj4515: [Sdoi2016]游戏
连个树剖都打不好 连个李超都打不好
把两点距离弄个树上前缀和化一下就变成y=k*dis[x]+b了
上树剖+李超树找最小、
记得李超树如果要换要把原来的下放啊!!
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define lc (now<<1) #define rc (now<<1|1) #define mid ((ql+qr)/2) using namespace std; typedef long long LL; const LL _=1e2; const LL maxn=1e5+_; const LL fbin=(1<<17)+_; const LL inf=123456789123456789LL; int n; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void write(LL d) { if(d<0){putchar('-');d=-d;} if(d>=10)write(d/10); putchar(d%10+'0'); } //----------------------------------------------------def----------------------------------------------------------- struct node { int x,y,next; LL d; }a[2*maxn];int len,last[maxn]; void ins(int x,int y,LL d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=last[x];last[x]=len; } int fa[30][maxn],dep[maxn]; int son[maxn],tot[maxn]; void pre_tree_node(int x) { for(int i=1;(1<<i)<=dep[x];i++)fa[i][x]=fa[i-1][fa[i-1][x]]; tot[x]=1; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[0][x]) { fa[0][y]=x; dep[y]=dep[x]+1; pre_tree_node(y); if(son[x]==0||tot[son[x]]<tot[y])son[x]=y; tot[x]+=tot[y]; } } } int z,ys[maxn],tp[maxn]; LL dis[maxn]; void pre_tree_edge(int x,int F) { ys[x]=++z;tp[x]=F; if(son[x]!=0) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y==son[x]) { dis[z+1]=dis[ys[x]]+a[k].d; pre_tree_edge(son[x],F); break; } } } for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[0][x]&&y!=son[x]) { dis[z+1]=dis[ys[x]]+a[k].d; pre_tree_edge(y,y); } } } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=25;i>=0;i--) if(dep[x]-dep[y]>=(1<<i))x=fa[i][x]; if(x==y)return x; for(int i=25;i>=0;i--) if(dep[x]>=(1<<i)&&fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y]; return fa[0][x]; } //--------------------------------------------------------pre------------------------------------------------------------ struct line{LL k,b;line(){} line(LL K,LL B){k=K,b=B;} LL gety(LL x){return k*x+b;}}; double jdx(line l1,line l2){return (double)(l2.b-l1.b)/(double)(l1.k-l2.k);} struct segtree { line l;LL c; segtree(){} }tr[2*fbin]; int maxdep; void update(int now,int ql,int qr) { tr[now].c=tr[now].l.gety(tr[now].l.k>0?dis[ql]:dis[qr]); if(ql!=qr)tr[now].c=min(tr[now].c,min(tr[lc].c,tr[rc].c)); } void bt(int now,int ql,int qr,line g) { tr[now].l=g,tr[now].c=inf; if(ql==qr)return ; bt(lc,ql,mid,g),bt(rc,mid+1,qr,g); } void change(int now,int ql,int qr,int l,int r,line g) { if(ql==qr) { if( tr[now].l.k==g.k&&tr[now].l.b>g.b || !((jdx(g,tr[now].l)<double(dis[mid]))^(g.k<tr[now].l.k)) ) tr[now].l=g; } else if(ql==l&&qr==r) { double p=jdx(g,tr[now].l); if(tr[now].l.k==g.k&&tr[now].l.b>g.b)tr[now].l=g; else if(p<double(dis[ql])) { if(g.k<tr[now].l.k)tr[now].l=g; } else if(double(dis[qr])<p) { if(g.k>tr[now].l.k)tr[now].l=g; } else { if(p<double(dis[mid])) { if(g.k<tr[now].l.k)change(lc,ql,mid,l,mid,tr[now].l),tr[now].l=g; else change(lc,ql,mid,l,mid,g); } else { if(g.k>tr[now].l.k)change(rc,mid+1,qr,mid+1,r,tr[now].l),tr[now].l=g; else change(rc,mid+1,qr,mid+1,r,g); } } } else { if(r<=mid) change(lc,ql,mid,l,r,g); else if(mid+1<=l)change(rc,mid+1,qr,l,r,g); else change(lc,ql,mid,l,mid,g),change(rc,mid+1,qr,mid+1,r,g); } update(now,ql,qr); } LL ans; void getmin(int now,int ql,int qr,int l,int r) { if(l==ql&&qr==r){ans=min(ans,tr[now].c);return ;} ans=min(ans,tr[now].l.gety(tr[now].l.k>0?dis[max(ql,l)]:dis[min(qr,r)])); if(r<=mid) getmin(lc,ql,mid,l,r); else if(mid+1<=l)getmin(rc,mid+1,qr,l,r); else getmin(lc,ql,mid,l,mid),getmin(rc,mid+1,qr,mid+1,r); } //------------------------------------------------------segtree---------------------------------------------------------- void Change(int x,int lca,line l) { int tx=tp[x]; while(tx!=tp[lca]) { change(1,1,n,ys[tx],ys[x],l); x=fa[0][tx],tx=tp[x]; } change(1,1,n,ys[lca],ys[x],l); } void Getmin(int x,int lca) { int tx=tp[x]; while(tx!=tp[lca]) { getmin(1,1,n,ys[tx],ys[x]); x=fa[0][tx],tx=tp[x]; } getmin(1,1,n,ys[lca],ys[x]); } //-------------------------------------------------------solve----------------------------------------------------------- int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int m,x,y,dd; n=read(),m=read(); for(int i=1;i<n;i++) { x=read(),y=read(),dd=read(); ins(x,y,dd),ins(y,x,dd); } pre_tree_node(1); pre_tree_edge(1,1); bt(1,1,n,line(0,inf)); int op;LL a,b; while(m--) { op=read(); if(op==1) { x=read(),y=read(),a=read(),b=read(); int lca=LCA(x,y); Change(x,lca,line(-a,b+a*dis[ys[x]])); Change(y,lca,line(a,b+a*(dis[ys[x]]-2*dis[ys[lca]]))); } else { x=read(),y=read(); int lca=LCA(x,y); ans=inf; Getmin(x,lca); Getmin(y,lca); write(ans),putchar('\n'); } } return 0; }
pain and happy in the cruel world.