BZOJ4515: [Sdoi2016]游戏
来源:互联网 发布:淘宝都市丽人 编辑:程序博客网 时间:2024/06/05 07:26
传送门(这篇写得比我好
qwq
s到t的链可以拆成两条纵链
令dis[x]表示x到根的距离
对于一条纵链上的一个点x,添加的数就可以看成
(dis[x]-dis[t])* k+b
=dis[x]*k-dis[t]*k+b
=k*dis[x]+B
很像直线的表达式y=kx+b
树剖,问题变成线段树维护多条直线在区间内的最小值
对于一条链,因为这个区间内的dis是递增的即x坐标递增,这个操作相当于给线段树一个区间上覆盖一条直线
在区间上打永久化标记为覆盖这个区间的直线,当遇到新的直线时,设加入直线f1,当前覆盖这个区间的直线f2,如果f1(l)< f2(l)&&f1(r)< f2(r) 那么可以用f1代替f2,都大于则没有用,否则递归下去,因为最多只有一个交点,这个交点不在左就在右,所以可以保证复杂度
code:
#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline ll _min(const ll a,const ll b){return a<b?a:b;}inline void down(ll &x,const ll &y){if(x>y)x=y;}const int maxn = 210000;const int maxm = 210000;const ll inf = 123456789123456789ll;int n,m;struct edge{ int y,c,nex; edge(){} edge(const int _y,const int _c,const int _nex){y=_y;c=_c;nex=_nex;}}a[maxn<<1]; int len,fir[maxn];inline void ins(const int x,const int y,const int c){a[++len]=edge(y,c,fir[x]);fir[x]=len;}ll dis[maxn];int f[maxn],top[maxn],siz[maxn],son[maxn],dep[maxn],w[maxn];void dfs(const int x){ siz[x]=1; for(int k=fir[x];k;k=a[k].nex) { const int y=a[k].y; if(y!=f[x]) { dep[y]=dep[x]+1; dis[y]=dis[x]+(ll)a[k].c; f[y]=x; dfs(y); if(siz[son[x]]<siz[y]) son[x]=y; siz[x]+=siz[y]; } }}int z;ll s[maxn];void build(const int x,const int tp){ s[w[x]=++z]=dis[x]; top[x]=tp; if(son[x]) build(son[x],tp); for(int k=fir[x];k;k=a[k].nex) { const int y=a[k].y; if(y!=f[x]&&y!=son[x]) build(y,y); }}struct segment{ bool flag; ll a,b,mn; segment(){flag=false;mn=inf;}}seg[maxn<<2];int lx,rx;ll fa,fb;void up(const int x){ int lc=x<<1,rc=lc|1; down(seg[x].mn,_min(seg[lc].mn,seg[rc].mn));}void upd(const int x,const int l,const int r){ if(rx<l||r<lx) return; if(lx<=l&&r<=rx) { ll cl=s[l]*fa+fb,cr=s[r]*fa+fb; if(seg[x].flag) { ll cl2=s[l]*seg[x].a+seg[x].b,cr2=s[r]*seg[x].a+seg[x].b; if(cl>=cl2&&cr>=cr2) return; else if( (cl<cl2&&cr>=cr2)||(cl>=cl2&&cr<cr2) ) { int mid=l+r>>1,lc=x<<1,rc=lc|1; upd(lc,l,mid); upd(rc,mid+1,r); up(x); return; } } seg[x].flag=true; seg[x].a=fa,seg[x].b=fb; down(seg[x].mn,_min(cl,cr)); return; } int mid=l+r>>1,lc=x<<1,rc=lc|1; upd(lc,l,mid); upd(rc,mid+1,r); up(x);}ll ret;void query(const int x,const int l,const int r){ if(rx<l||r<lx) return; if(lx<=l&&r<=rx) { down(ret,seg[x].mn); return ; } int mid=l+r>>1,lc=x<<1,rc=lc|1; if(seg[x].flag) { ll cl=s[max(lx,l)]*seg[x].a+seg[x].b,cr=s[min(rx,r)]*seg[x].a+seg[x].b; down(ret,_min(cl,cr)); } query(lc,l,mid); query(rc,mid+1,r);}int LCA(int x,int y){ int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); x=f[f1],f1=top[x]; } return dep[x]<dep[y]?x:y;}void change(int S,int T,int A,int B){ int tp=LCA(S,T),ft=top[tp]; int x=S,f1=top[x]; while(dep[x]>=dep[tp]) { if(f1==ft) f1=tp; fa=-A,fb=B+(ll)A*dis[S],lx=w[f1],rx=w[x],upd(1,1,n); x=f[f1],f1=top[x]; } int y=T,f2=top[y]; while(dep[y]>=dep[tp]) { if(f2==ft) f2=tp; fa=A,fb=B+(ll)A*(dis[S]-dis[tp]*2ll),lx=w[f2],rx=w[y],upd(1,1,n); y=f[f2],f2=top[y]; }}ll solve(int x,int y){ ll re=inf; int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); lx=w[f1],rx=w[x],ret=inf,query(1,1,n); down(re,ret); x=f[f1],f1=top[x]; } if(dep[x]>dep[y]) swap(x,y); lx=w[x],rx=w[y],ret=inf,query(1,1,n); down(re,ret); return re;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); ins(x,y,c); ins(y,x,c); } dep[1]=1; dfs(1); build(1,1); for(int i=1;i<=m;i++) { int type,s,t; scanf("%d%d%d",&type,&s,&t); if(type==1) { int A,B; scanf("%d%d",&A,&B); change(s,t,A,B); } else printf("%lld\n",solve(s,t)); } return 0;}
阅读全文
0 0
- bzoj4515【SDOI2016】游戏
- bzoj4515: [Sdoi2016]游戏
- 【SDOI2016】bzoj4515 游戏
- bzoj4515 [Sdoi2016]游戏
- BZOJ4515: [Sdoi2016]游戏
- [BZOJ4515][Sdoi2016]游戏(树链剖分)
- 【bzoj4515】【SDOI2016】【游戏】【线段树+树链剖分】
- [BZOJ4515][SDOI2016] 游戏 - 树链剖分 - 半平面交 - 标记永久化
- [树链剖分+李超线段树] BZOJ4515: [Sdoi2016]游戏
- [树链剖分 李超线段树] BZOJ4515 [Sdoi2016] 游戏
- 【树链剖分+李超线段树】BZOJ4515(Sdoi2016)[游戏]题解
- BZOJ 4515 SDOI2016 游戏
- BZOJ 4515: [Sdoi2016]游戏
- [bzoj4600][SDOI2016]硬币游戏
- 4515: [Sdoi2016]游戏
- BZOJ 4515 [Sdoi2016]游戏
- BZOJ 4515 [Sdoi2016]游戏
- 4600: [Sdoi2016]硬币游戏
- 关于快排函数的一些例子
- 【长期更新】noip之后每日总结
- Codeforces Round #379 (Div. 2) C. Anton and Making Potions 枚举+二分
- java设计模式 -- 单例模式
- Python学习日记 第二天
- BZOJ4515: [Sdoi2016]游戏
- 网友们经历过的最难调试的Bug
- 【JavaScript】自定义console对象
- 去除织梦DedeCMS列表和文章分页标签源码中的
- 扫描WiFi 并展示到ListView
- 自顶向下,逐步求精
- caffe参数说明
- CF-448(Div.2)-A. Pizza Separation
- Fourier Series