您的位置:首页 > 其它

bzoj4515 [Sdoi2016]游戏 标记永久线段树+链剖+差分

2018-03-04 10:33 288 查看
树上路径问题还有一个比较好的差分就是利用到根节点的信息。。
题目的形式显然是一个一次函数,于是想到维护一次函数最小值
上升路径就是: A(d[x]-d[o])+B   =  -Ad[o]+(B-Ad[x]);
下降路径:       A(d[x]+d[o]-2*d[lca])+B = Ad[o]+(B+A(d[o]-2*d[lca]))
维护新函数  ,查询的时候分下去查。。由于需要区间答案,所以就需要up
标记永久就不需要down
注:
1、注意区分原树和线段树
2、注意查询的内容范围外、范围内
3、注意运算顺序
4、注意 long long 
5、注意d 和 dui 对应关系
码:#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100005
#define ll long long
bool cz[N<<2];
int n,m,fu
,sz
,zhong[N<<1],tot,hou[N<<1],xia
,wz
,top
,hson
,cnt,op,lca,x,y,i,dui
;
ll v[N<<1],d
,a,b,c,kk[N<<2],bb[N<<2],A,B,ans,minn[N<<2];
void jian(int a,int b,ll c)
{
++tot;hou[tot]=xia[a],xia[a]=tot,zhong[tot]=b,v[tot]=c;
}
void jia(int a,int b,ll c)
{
jian(a,b,c);
jian(b,a,c);
}
void dfs1(int o,int fa,ll dis)
{
sz[o]=1;
d[o]=dis;
fu[o]=fa;
int i,nd;
for(i=xia[o];i!=-1;i=hou[i])
{
nd=zhong[i];
if(nd==fa)continue;
dfs1(nd,o,dis+v[i]);
if(sz[hson[o]]<sz[nd])hson[o]=nd;
sz[o]+=sz[nd];
}
}
void dfs2(int o,int tap)
{
top[o]=tap;
int i,nd;
wz[o]=++cnt;
dui[cnt]=o;
if(hson[o])dfs2(hson[o],tap);
for(i=xia[o];i!=-1;i=hou[i])
{
nd=zhong[i];
if(nd==fu[o]||nd==hson[o])continue;
dfs2(nd,nd);
}
}
void up(int o,ll l,ll mid,ll r)
{
minn[o]= cz[o]? min(kk[o]*d[dui[l]]+bb[o],kk[o]*d[dui[r]]+bb[o]):123456789123456789 ;
minn[o]=min(min(minn[o<<1],minn[o<<1|1]),minn[o]);
}
void gai(int o,int l,int r)
{int mid=(l+r)/2;
if(op==1)//上升
{
if(a<=l&&r<=b)
{
if(cz[o]==0||(kk[o]*d[dui[l]]+bb[o] > -A*d[dui[l]]+(B+A*d[x]) && kk[o]*d[dui[r]]+bb[o] > -A*d[dui[r]]+(B+A*d[x]) ))
{
cz[o]=1;
kk[o]=-A;
bb[o]=B+A*d[x];
minn[o]=min(minn[o],min( -A*d[dui[l]]+(B+A*d[x]),-A*d[dui[r]]+(B+A*d[x])));
return ;
}
if(kk[o]*d[dui[l]]+bb[o] <= -A*d[dui[l]]+(B+A*d[x]) && kk[o]*d[dui[r]]+bb[o] <= -A*d[dui[r]]+(B+A*d[x]) )
{
return ;
}
long double jd=1.0000000*((B+A*d[x])-bb[o])/(1.0000000*(kk[o]+A));
if(jd<=d[dui[mid]])
{
gai(o<<1,l,mid);
if(kk[o]*d[dui[r]]+bb[o] > - A*d[dui[r]]+(B+A*d[x]) )gai(o<<1|1,mid+1,r);
}else
{
gai(o<<1|1,mid+1,r);
if(kk[o]*d[dui[l]]+bb[o] > -A*d[dui[l]]+(B+A*d[x]) )gai(o<<1,l,mid);
}
}else
{
if(a<=mid)gai(o<<1,l,mid);
if(b>mid)gai(o<<1|1,mid+1,r);
}
}
if(op==0)//下降
{
if(a<=l&&r<=b)
{
if(cz[o]==0||(kk[o]*d[dui[l]]+bb[o] > A*d[dui[l]]+(B+A*(d[x]-2*d[lca])) && kk[o]*d[dui[r]]+bb[o] > A*d[dui[r]]+(B+A*(d[x]-2*d[lca])) ))
{
cz[o]=1;
kk[o]=A;
bb[o]=B+A*(d[x]-2*d[lca]);
minn[o]=min(min(A*d[dui[l]]+(B+A*(d[x]-2*d[lca])), A*d[dui[r]]+(B+A*(d[x]-2*d[lca])) ),minn[o]);
return ;
}
if(kk[o]*d[dui[l]]+bb[o] <= A*d[dui[l]]+(B+A*(d[x]-2*d[lca])) && kk[o]*d[dui[r]]+bb[o] <= A*d[dui[r]]+(B+A*(d[x]-2*d[lca])) )
{
return ;
}
long double jd=1.0000000*(B+A*(d[x]-2*d[lca])-bb[o])/(1.0000000*(kk[o]-A));
if(jd<=d[dui[mid]])
{
gai(o<<1,l,mid);
if(kk[o]*d[dui[r]]+bb[o] > A*d[dui[r]]+(B+A*(d[x]-2*d[lca])) )gai(o<<1|1,mid+1,r);
}else
{
gai(o<<1|1,mid+1,r);
if(kk[o]*d[dui[l]]+bb[o] > A*d[dui[l]]+(B+A*(d[x]-2*d[lca])) )gai(o<<1,l,mid);
}
}else
{
if(a<=mid)gai(o<<1,l,mid);
if(b>mid)gai(o<<1|1,mid+1,r);
}
}
if(op==2)
{
if(cz[o])ans=min(min( d[dui[min(1ll*r,b)]]*kk[o]+bb[o], d[dui[max(1ll*l,a)]]*kk[o]+bb[o] ),ans);
if(a<=l&&r<=b)
{
ans=min(ans,minn[o]);
return ;
}
if(a<=mid)
gai(o<<1,l,mid);
if(b>mid)
gai(o<<1|1,mid+1,r);
}
if(l!=r)up(o,l,mid,r);
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]])swap(x,y);
x=fu[top[x]];
}
if(d[x]>d[y])swap(x,y);
return x;
}
void work(int x,int y)
{ lca=LCA(x,y);
while(top[x]!=top[lca])
{
a=wz[top[x]];b=wz[x];
gai(1,1,n);
x=fu[top[x]];
}
a=wz[lca];b=wz[x];
gai(1,1,n);
if(op==1)op=0;
while(top[y]!=top[lca])
{
a=wz[top[y]];b=wz[y];
gai(1,1,n);
y=fu[top[y]];
}
a=wz[lca];b=wz[y];
gai(1,1,n);
}
void csh(int o,int l,int r)
{
minn[o]=123456789123456789;
if(l==r)return ;
int mid=(l+r)>>1;
csh(o<<1,l,mid);
csh(o<<1|1,mid+1,r);
}
int main()
{
memset(xia,-1,sizeof(xia));
scanf("%d%d",&n,&m);
csh(1,1,n);
for(i=1;i<n;i++)
{
scanf("%lld%lld%lld",&a,&b,&c);
jia(a,b,c);
}
dfs1(1,1,0);
dfs2(1,1);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld%lld",&x,&y,&A,&B);
work(x,y);
}else
{
ans=123456789123456789;
scanf("%d%d",&x,&y);
work(x,y);
printf("%lld\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: