Description
有一个神秘好人跟Bdcxq玩一个游戏,如果Bdcxq成功完成了这个游戏,那么他将会得到一件礼物。
这个游戏是这样的:
有一个梯子形的图如下,每条边都有一个权值。
神秘好人一开始会告诉Bdcxq每条边的权值。
然后神秘好人会做这样的事情:
1.神秘好人会修改某条边的权值;
2.神秘老人会问你从一个点走到另一个点所需经过边权和最小的权值和。
如果Bdcxq一直能答对问题,那么他就完成了游戏,也能得到礼物。
现在他请你编一个程序来帮他完成游戏。
Input
输入文件的第一行包含一个整数N,表示梯子总共含有2N个点,第一行从左至右分别标号为1,3,……,2N-1,第二行从左至右分别标号为2,4,……,2N。
接下来有三行。
第一行有N-1个整数,依次表示上层相邻两点间的初始权值。
第二行有N个整数,依次表示两层之间的边的初始权值。
第三行有N-1个整数,依次表示下层相邻两点间的初始权值。
接下来一行包含一个整数M,表示神秘好人在游戏开始后的操作。
接下来M行:
每行第一个整数若是0,表示这是一个修改操作,接下来会有3个整数Ai,Bi,Ci,Ai为0,1,2分别代表这条边属于上层边,中间边和下层边,Bi表示这条边是这一层从左向右数的第Bi条边,Ci表示要修改成的边权。
每行第一个整数若是1,表示这是一个询问操作,接下来会有2个整数Ai,Bi,询问Ai到Bi的经过边的最小权值和。
Output
对于每次询问操作你需要输出一行包含一个整数,为最小的边权值和。
用线段树维护区间内 左上/下角 走到 右上/下角 的最短路长度,另外特判最短路走到区间外绕一圈的情况
#include<bits/stdc++.h> typedef long long i64; const int N=100007; char buf[15000007],*ptr=buf-1; int _(){ int x=0,f=1; while(*ptr<48)*ptr++=='-'?f=-1:0; while(*ptr>47)x=x*10+*ptr++-48; return x*f; } int n,v[3][N]; int _l,_r; i64 min(i64 a,i64 b){return a<b?a:b;} struct node{ #define F(a,b,c) lc->a+b+rc->c node*lc,*rc,*f; int L,R,M; i64 ab,ad,cb,cd,vm,v0,v1,v2,vl,vr; void up0(){ ab=min(F(ab,v0,ab),F(ad,v2,cb)); cd=min(F(cb,v0,ad),F(cd,v2,cd)); ad=min(F(ab,v0,ad),F(ad,v2,cd)); cb=min(F(cb,v0,ab),F(cd,v2,cb)); } void upl(){vl=min(rc->vl,rc->vm+v0+v2+lc->vl);} void upr(){vr=min(lc->vr,lc->vm+v0+v2+rc->vr);} void upx(){vm=lc->vm+rc->vm+v0+v2;} void up(){up0(),upx(),upl(),upr();} void init1(){ ad=cb=v1=vl=vr=v[1][L]; ab=cd=vm=0; } void init2(){ v0=v[0][M]; v2=v[2][M]; up(); } i64 query(int x,int y,i64 ml,i64 mr){ if(x){ if(y)return min(min(cd,ab+ml+mr),min(ml+ad,mr+cb)); return min(min(cb,ad+ml+mr),min(ml+ab,mr+cd)); } if(y)return min(min(ad,cb+ml+mr),min(ml+cd,mr+ab)); return min(min(ab,cd+ml+mr),min(ml+cb,mr+ad)); } node*gl(); node*gr(); node*get(); #undef F }ns[N*2+1007],*np=ns,*rt,*nw[2][N],*np1; node*node::get(){ if(_l<=L&&R<=_r)return this; if(_r<=M)return lc->get(); if(_l>M)return rc->get(); node*w=np1++; w->v0=v0,w->v2=v2; w->lc=lc->get(); w->rc=rc->get(); w->up0(); return w; } node*node::gl(){ if(R<_l)return this; if(M+1>=_l)return lc->gl(); node*w=np1++; w->v0=v0,w->v2=v2; w->lc=lc; w->rc=rc->gl(); w->upx(),w->upl(); return w; } node*node::gr(){ if(L>_r)return this; if(M<=_r)return rc->gr(); node*w=np1++; w->v0=v0,w->v2=v2; w->rc=rc; w->lc=lc->gr(); w->upx(),w->upr(); return w; } node*build(int L,int R){ node*w=np++; w->L=L,w->R=R; if(L==R){ w->init1(); nw[1][L]=w; }else{ int M=L+R>>1; w->M=M; (w->lc=build(L,M))->f=w; (w->rc=build(M+1,R))->f=w; w->init2(); nw[0][M]=w; } return w; } int main(){ fread(buf,1,sizeof(buf),stdin); n=_(); for(int i=1;i<n;++i)v[0][i]=_(); for(int i=1;i<=n;++i)v[1][i]=_(); for(int i=1;i<n;++i)v[2][i]=_(); rt=build(1,n); for(int q=_();q;--q){ if(_()){ np1=np; int x=_()+1,y=_()+1; if(x>y)std::swap(x,y); _l=x>>1,_r=y>>1; node*a=rt->get(); i64 ml=1ll<<60,mr=1ll<<60; if(_l>1)ml=rt->gl()->vl+v[0][_l-1]+v[2][_l-1]; if(_r<n)mr=rt->gr()->vr+v[0][_r]+v[2][_r]; printf("%lld\n",a->query(x&1,y&1,ml,mr)); }else{ int tp=_(),w=_(),x=_(); v[tp][w]=x; node*a=nw[tp&1][w]; if(tp&1)a->init1(); else a->init2(); for(a=a->f;a;a=a->f)a->up(); } } return 0; }