[SDOI2016]游戏
Description
Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
Input
第一行两个数字 n、m,表示树的点数和进行的操作数。
接下来 n−1 行,每行三个数字 u、v、w,表示树上有一条连接 u、v 的边,长度是 w。
接下来 m 行。每行第一个数字是 1 或 2。
若第一个数是 1,表示 Alice 进行操作,接下来四个数字 s、t、a、b。
若第一个数是 2,表示 Bob 进行操作,接下来四个数字 s、t。
Output
每当 Bob 进行操作,输出一行一个数,表示他能够选择的最小的数字
Sample Input
3 5
1 2 10
2 3 20
2 1 3
1 2 3 5 6
2 2 3
1 2 3 -5 -6
2 2 3
1 2 10
2 3 20
2 1 3
1 2 3 5 6
2 2 3
1 2 3 -5 -6
2 2 3
Sample Output
123456789123456789
6
-106
6
-106
HINT
n≤100000,m≤100000,∣a∣≤10000,0<=w,|b|<=10^9
对于A*dis+B,将它分成s->lca,lca->t
s->lca:
A*(d[s]-d[x])+B=-A*d[x]+A*d[s]+B
lca->t:
A*(d[s]+d[x]-2*d[lca])+B=A*d[x]+A*d[s]-2*A*d[lca]+B
在一条链上显然d[fa]<d[son],所以相当于把一个一次函数放入几个线段
查询就是求区间线段最小值
然后就是lichao线段树
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long lol; 8 struct Node 9 { 10 int next,to; 11 lol dis; 12 }edge[200001]; 13 struct Line 14 { 15 lol k,b; 16 bool id; 17 }tree[400001]; 18 lol ans,d[100001],val[400001],inf=123456789123456789; 19 int num,head[100001],size[100001],fa[100001][21],dep[100001],son[100001],dfn[100001],cnt,id[100001],top[100001],n,m; 20 void add(int u,int v,lol w) 21 { 22 num++; 23 edge[num].next=head[u]; 24 head[u]=num; 25 edge[num].to=v; 26 edge[num].dis=w; 27 } 28 void dfs1(int x,int pa) 29 {int i; 30 size[x]=1; 31 for (i=head[x];i;i=edge[i].next) 32 { 33 int v=edge[i].to; 34 if (v==pa) continue; 35 fa[v][0]=x; 36 d[v]=d[x]+edge[i].dis; 37 dep[v]=dep[x]+1; 38 dfs1(v,x); 39 size[x]+=size[v]; 40 if (size[v]>size[son[x]]) son[x]=v; 41 } 42 } 43 void dfs2(int x,int pa,int tp) 44 {int i; 45 dfn[x]=++cnt; 46 id[cnt]=x; 47 top[x]=tp; 48 if (son[x]) dfs2(son[x],x,tp); 49 for (i=head[x];i;i=edge[i].next) 50 { 51 int v=edge[i].to; 52 if (v==pa||v==son[x]) continue; 53 dfs2(v,x,v); 54 } 55 } 56 int lca(int x,int y) 57 { 58 while (top[x]!=top[y]) 59 { 60 if (d[top[x]]<d[top[y]]) swap(x,y); 61 x=fa[top[x]][0]; 62 } 63 if (d[x]<d[y]) return x; 64 else return y; 65 } 66 lol cal(Line a,lol x) 67 { 68 return a.k*x+a.b; 69 } 70 double cross(Line x,Line y) 71 { 72 return (x.b-y.b)/(1.0*(y.k-x.k)); 73 } 74 void add_min(int rt,int l,int r,Line x) 75 { 76 if (!tree[rt].id) 77 { 78 tree[rt]=x; 79 return; 80 } 81 lol f1=cal(x,d[id[l]]);lol f2=cal(tree[rt],d[id[l]]); 82 lol f3=cal(x,d[id[r]]);lol f4=cal(tree[rt],d[id[r]]); 83 if (f1>=f2&&f3>=f4) return; 84 else 85 if (f1<=f2&&f3<=f4) 86 {tree[rt]=x;} 87 else 88 { 89 double p=cross(tree[rt],x); 90 int mid=(l+r)/2; 91 if (f1<=f2) 92 { 93 if (p<=d[id[mid]]) add_min(rt<<1,l,mid,x); 94 else add_min(rt<<1|1,mid+1,r,tree[rt]),tree[rt]=x; 95 } 96 else 97 { 98 if (p<=d[id[mid]]) add_min(rt<<1,l,mid,tree[rt]),tree[rt]=x; 99 else add_min(rt<<1|1,mid+1,r,x); 100 } 101 } 102 } 103 void update(int rt,int l,int r,int L,int R,Line x) 104 { 105 val[rt]=min(val[rt],min(cal(x,d[id[L]]),cal(x,d[id[R]]))); 106 if (l==L&&r==R) 107 { 108 add_min(rt,l,r,x); 109 return; 110 } 111 int mid=(l+r)/2; 112 if (R<=mid) update(rt<<1,l,mid,L,R,x); 113 else if (L>mid) update(rt<<1|1,mid+1,r,L,R,x); 114 else 115 { 116 update(rt<<1,l,mid,L,mid,x); 117 update(rt<<1|1,mid+1,r,mid+1,R,x); 118 } 119 } 120 void query(int rt,int l,int r,int L,int R) 121 { 122 if (tree[rt].id) 123 { 124 ans=min(ans,min(cal(tree[rt],d[id[L]]),cal(tree[rt],d[id[R]]))); 125 } 126 if (l==L&&r==R) 127 { 128 ans=min(ans,val[rt]); 129 return; 130 } 131 int mid=(l+r)/2; 132 if (R<=mid) query(rt<<1,l,mid,L,R); 133 else if (L>mid) query(rt<<1|1,mid+1,r,L,R); 134 else 135 { 136 query(rt<<1,l,mid,L,mid);query(rt<<1|1,mid+1,r,mid+1,R); 137 } 138 } 139 void build(int rt,int l,int r) 140 { 141 val[rt]=inf; 142 if (l==r) return; 143 int mid=(l+r)/2; 144 build(rt*2,l,mid); 145 build(rt*2+1,mid+1,r); 146 } 147 int main() 148 {int i,u,v,j,opt,s,t,x,y; 149 lol w,A,B; 150 cin>>n>>m; 151 for (i=1;i<=n-1;i++) 152 { 153 scanf("%d%d%lld",&u,&v,&w); 154 add(u,v,w);add(v,u,w); 155 } 156 dfs1(1,0); 157 dfs2(1,0,1); 158 for (i=1;i<=20;i++) 159 { 160 for (j=1;j<=n;j++) 161 fa[j][i]=fa[fa[j][i-1]][i-1]; 162 } 163 build(1,1,n); 164 for (i=1;i<=m;i++) 165 { 166 scanf("%d",&opt); 167 if (opt==1) 168 { 169 scanf("%d%d%lld%lld",&s,&t,&A,&B); 170 int z=lca(s,t); 171 x=s;y=t; 172 while (top[x]!=top[z]) 173 { 174 update(1,1,n,dfn[top[x]],dfn[x],(Line){-A,B+A*d[s],1}); 175 x=fa[top[x]][0]; 176 } 177 update(1,1,n,dfn[z],dfn[x],(Line){-A,B+A*d[s],1}); 178 while (top[y]!=top[z]) 179 { 180 update(1,1,n,dfn[top[y]],dfn[y],(Line){A,B-2*A*d[z]+A*d[s],1}); 181 y=fa[top[y]][0]; 182 } 183 update(1,1,n,dfn[z],dfn[y],(Line){A,B-2*A*d[z]+A*d[s],1}); 184 } 185 else 186 { 187 scanf("%d%d",&s,&t); 188 int z=lca(s,t); 189 x=s;y=t;ans=inf; 190 while (top[x]!=top[z]) 191 { 192 query(1,1,n,dfn[top[x]],dfn[x]); 193 x=fa[top[x]][0]; 194 } 195 query(1,1,n,dfn[z],dfn[x]); 196 while (top[y]!=top[z]) 197 { 198 query(1,1,n,dfn[top[y]],dfn[y]); 199 y=fa[top[y]][0]; 200 } 201 query(1,1,n,dfn[z],dfn[y]); 202 printf("%lld\n",ans); 203 } 204 } 205 }