4515: [Sdoi2016]游戏
2016-08-18 20:41
405 查看
4515: [Sdoi2016]游戏
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 396 Solved: 178
[Submit][Status][Discuss]
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 51 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
1234567891234567896
-106
HINT
n≤100000,m≤100000,∣a∣≤10000,0<=w,|b|<=10^9Source
鸣谢Menci上传[Submit][Status][Discuss]
今天算是栽在这上面了,,日,,细节真多
总体思路显然:树链剖分+李超树
从s到Lca一段,从Lca到t一段
可分别用不同的斜率和截距表示,便于处理
即将原数据稍加修改得(详见代码)
然后是,,维护一个区间最低点
更新时刻有:
本区间被新线段覆盖
更新了子区间
记得更新区间最低点时不能舍去以前的点
查询答案的时候,从上往下一边找最低点一边用覆盖区间的线段尝试更新
日啊,,,调了半天,,真的是半天(from 12:00 to 20:30)
#include<iostream> #include<cstdio> #include<queue> #include<vector> #include<bitset> #include<algorithm> #include<cstring> #include<map> #include<stack> #include<set> #include<cmath> #include<ext/pb_ds/priority_queue.hpp> using namespace std; const int maxn = 1E5 + 10; const int T = 20; typedef long long LL; const LL Inf = 123456789123456789; typedef double DB; struct E{ int to,w; E (int _to = 0,int _w = 0) {to = _to; w = _w;} }; int n,m,cnt,Root,Lca,I,fa[maxn][20],len[maxn],Nex[maxn],L[maxn] ,First[maxn],pos[maxn],siz[maxn],root[maxn],lc[maxn*T],rc[maxn*T]; LL ans,Min[maxn*T],Light[maxn],k[maxn*T],b[maxn*T],dis2[maxn],dis[maxn]; bool Huge[maxn]; vector <E> v[maxn]; vector <int> Road[maxn]; int New() {++cnt; k[cnt] = 0; b[cnt] = Min[cnt] = Inf; return cnt;} int Getlc(int o) {return lc[o]?lc[o]:lc[o] = New();} int Getrc(int o) {return rc[o]?rc[o]:rc[o] = New();} void dfs(int x,int from) { Light[x] = Inf; siz[x] = 1; int Max = 0,po; for (int i = 1; i < 20; i++) fa[x][i] = fa[fa[x][i-1]][i-1]; for (int i = 0; i < v[x].size(); i++) { int to = v[x][i].to; if (to == from) continue; fa[to][0] = x; dis[to] = dis[x] + 1LL*v[x][i].w; L[to] = L[x] + 1; dfs(to,x); siz[x] += siz[to]; if (siz[to] > Max) Max = siz[to],po = to; } if (siz[x] > 1) Huge[po] = 1,Nex[x] = po; } void dfs2(int x,int from,int Len) { if (siz[x] == 1) { if (Huge[x]) { len[x] = Len + 1; First[x] = x; root[x] = New(); pos[x] = 1; k[cnt] = 0; b[cnt] = Inf; dis2[x] = 0; Road[x].push_back(0); Road[x].push_back(x); } return; } Len = Huge[x]?++Len:0; for (int i = 0; i < v[x].size(); i++) { int to = v[x][i].to; if (to == from) continue; dfs2(to,x,Len); } if (Huge[x]) { root[x] = root[Nex[x]]; len[x] = len[Nex[x]]; First[x] = First[Nex[x]]; pos[x] = pos[Nex[x]] + 1; dis2[x] = dis2[Nex[x]] + dis[Nex[x]] - dis[x]; Road[First[x]].push_back(x); } } void pushdown(int o,int belong,int l,int r,LL K,LL B) { int numl = Road[belong][l]; int numr = Road[belong][r]; LL A1 = dis2[numl]*K + B,A2 = dis2[numl]*k[o] + b[o]; LL B1 = dis2[numr]*K + B,B2 = dis2[numr]*k[o] + b[o]; Min[o] = min(Min[o],min(A1,B1)); if (A1 < A2 && B1 < B2) { Min[o] = min(Min[o],min(A1,B1)); k[o] = K; b[o] = B; return; } if (A1 >= A2 && B1 >= B2) return; DB x = (DB)(b[o] - B)/(DB)(K - k[o]); int Mid = Road[belong][(l+r)>>1]; LL mid = dis2[Mid]; Mid = pos[Mid]; if (x <= mid) { if (A1 > A2) pushdown(Getlc(o),belong,l,Mid,k[o],b[o]),k[o] = K,b[o] = B; else pushdown(Getlc(o),belong,l,Mid,K,B); } else { if (A1 > A2) pushdown(Getrc(o),belong,Mid+1,r,K,B); else pushdown(Getrc(o),belong,Mid+1,r,k[o],b[o]),k[o] = K,b[o] = B; } Min[o] = min(Min[o],min(Min[Getlc(o)],Min[Getrc(o)])); } void modify(int o,int belong,int l,int r,int ml,int mr,LL K,LL B) { if (ml <= l && r <= mr) {pushdown(o,belong,l,r,K,B); return;} int mid = (l + r) >> 1; if (ml <= mid) modify(Getlc(o),belong,l,mid,ml,mr,K,B); if (mr > mid) modify(Getrc(o),belong,mid+1,r,ml,mr,K,B); Min[o] = min(Min[o],min(Min[Getlc(o)],Min[Getrc(o)])); } int Quickfa(int x,int y) { for (int num = 0; y; y >>= 1,++num) if (y & 1) x = fa[x][num]; return x; } void Modify1(int x,LL K,LL B) { LL Dis = 0; for (; x != Lca; Dis += (dis[x] - dis[fa[x][0]]),x = fa[x][0]) { if (!Huge[x]) Light[x] = min(Light[x],K*Dis + B); else { if (pos[x] == 1) { if (L[x] - (len[x] - pos[x]) > L[Lca]) { modify(root[x],First[x],1,len[x],pos[x],len[x],K,B+Dis*K); Dis += dis[x]; x = Quickfa(x,len[x] - pos[x]); Dis -= dis[x]; } else { modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,K,B+Dis*K); return; } } else { if (L[x] - (len[x] - pos[x]) > L[Lca]) { modify(root[x],First[x],1,len[x],pos[x],len[x],K,B+(Dis-dis2[x])*K); Dis += dis[x]; x = Quickfa(x,len[x] - pos[x]); Dis -= dis[x]; } else { modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,K,B+(Dis-dis2[x])*K); return; } } } } } void Modify2(int x,LL K,LL B,LL Dis) { Dis += (dis[x] - dis[Lca]); for (; x != Lca; Dis -= (dis[x] - dis[fa[x][0]]),x = fa[x][0]) { if (!Huge[x]) Light[x] = min(Light[x],K*Dis + B); else { if (pos[x] == 1) { if (L[x] - (len[x] - pos[x]) > L[Lca]) { modify(root[x],First[x],1,len[x],pos[x],len[x],-K,B+Dis*K); Dis -= dis[x]; x = Quickfa(x,len[x] - pos[x]); Dis += dis[x]; } else { modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,-K,B+Dis*K); return; } } else { if (L[x] - (len[x] - pos[x]) > L[Lca]) { modify(root[x],First[x],1,len[x],pos[x],len[x],-K,B+(Dis+dis2[x])*K); Dis -= dis[x]; x = Quickfa(x,len[x] - pos[x]); Dis += dis[x]; } else { modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,-K,B+(Dis+dis2[x])*K); return; } } } } } LL query(int o,int belong,int l,int r,int ql,int qr) { LL QL = Road[belong][max(ql,l)]; QL = dis2[QL]; LL QR = Road[belong][min(qr,r)]; QR = dis2[QR]; LL A1 = QL*k[o] + b[o]; LL B1 = QR*k[o] + b[o]; if (ql <= l && r <= qr) return min(Min[o],min(A1,B1)); int mid = (l + r) >> 1; LL ret = Inf; if (ql <= mid) ret = min(ret,query(Getlc(o),belong,l,mid,ql,qr)); if (qr > mid) ret = min(ret,query(Getrc(o),belong,mid+1,r,ql,qr)); return min(ret,min(A1,B1)); } void Query(int x) { for (; x != Lca; x = fa[x][0]) { if (!Huge[x]) ans = min(ans,Light[x]); else { if (L[x] - (len[x] - pos[x]) > L[Lca]) { ans = min(ans,query(root[x],First[x],1,len[x],pos[x],len[x])); x = Quickfa(x,len[x] - pos[x]); } else { ans = min(ans,query(root[x],First[x],1,len[x],pos[x],pos[Lca]-1)); return; } } } } int getint() { char ch = getchar(); int ret = 0,multi = 1; while (ch < '0' || '9' < ch) { if (ch == '-') multi = -1; ch = getchar(); } while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar(); return ret*multi; } int LCA(int p,int q) { if (L[p] < L[q]) swap(p,q); int Log; for (Log = 0; L[p] - (1<<Log) >= 1; Log++); --Log; for (int j = Log; j >= 0; j--) if (L[p] - (1<<j) >= L[q]) p = fa[p][j]; if (p == q) return p; for (int j = Log; j >= 0; j--) if (fa[p][j] != fa[q][j]) p = fa[p][j],q = fa[q][j]; return fa[p][0]; } int main() { #ifdef DMC //freopen("DMC.txt","r",stdin); freopen("game20.in","r",stdin); freopen("test.txt","w",stdout); #endif n = getint(); m = getint(); for (int i = 1; i < n; i++) { int x = getint(),y = getint(),z = getint(); v[x].push_back(E(y,z)); v[y].push_back(E(x,z)); } Root = n/2; L[Root] = 1; dfs(Root,0); dfs2(Root,0,0); for (I = 1; I <= m; I++) { int typ = getint(),s = getint(),t = getint(); Lca = LCA(s,t); if (typ == 1) { LL K = getint(),B = getint(); if (Lca != s) Modify1(s,K,B); if (!Huge[Lca]) Light[Lca] = min(Light[Lca],(dis[s] - dis[Lca])*K + B); else { DB NewB = (dis[s] - dis[Lca] - dis2[Lca])*K+B; modify(root[Lca],First[Lca],1,len[Lca],pos[Lca],pos[Lca],K,NewB); } if (Lca != t) Modify2(t,K,B,dis[s] - dis[Lca]); } else { ans = Inf; if (s != Lca) Query(s); if (t != Lca) Query(t); if (!Huge[Lca]) ans = min(ans,Light[Lca]); else ans = min(ans,query(root[Lca],First[Lca],1,len[Lca],pos[Lca],pos[Lca])); printf("%lld\n",ans); } } return 0; }
相关文章推荐
- BZOJ 4515 [Sdoi2016]游戏
- bzoj4515 [Sdoi2016]游戏(树链剖分+超哥线段树)
- [bzoj4515][Sdoi2016]游戏-树链剖分+李超线段树
- [树链剖分 李超线段树] BZOJ4515 [Sdoi2016] 游戏
- bzoj 4515: [Sdoi2016]游戏 树链剖分+线段树
- bzoj千题计划276:bzoj4515: [Sdoi2016]游戏
- bzoj 4515 [Sdoi2016]游戏 线段树维护凸包
- BZOJ 4515 [Sdoi2016]游戏
- bzoj4515 [Sdoi2016]游戏
- BZOJ 4515: [Sdoi2016]游戏
- 【BZOJ4515】[Sdoi2016]游戏 树链剖分+线段树
- bzoj 4515: [Sdoi2016]游戏
- 【bzoj4515】【SDOI2016】【游戏】【线段树+树链剖分】
- bzoj 4515: [Sdoi2016]游戏 树链剖分
- 【BZOJ 4515】【SDOI 2016 Round1 Day1 T3】游戏
- [bzoj4515] [Sdoi2016]游戏
- bzoj 4515: [Sdoi2016]游戏(树链剖分+线段树)
- [BZOJ4515][SDOI2016] 游戏 - 树链剖分 - 半平面交 - 标记永久化
- [BZOJ4515][Sdoi2016]游戏(树链剖分)
- BZOJ 4515|SDOI 2016|游戏|树链剖分