LGP5618题解
有坑,但是不难(
看到题的第一眼使用线段树,对区间维护两个状态,上面和下面是否连通。
然后你发现会被环给 gank 掉。
于是重新设状态,设 \(w[0/1][0/1]\) 表示左右端点中,上下节点是否连通。
这个相当好转移,只需要考虑合并的位置是否处于同一个连通块然后决定加上 \(x+y\) 还是 \(\min(x,y)\) 即可。
复杂度 \(O(m\log n)\) 比那个在环上删边的状态不知道高到哪里去了
#include<cstdio>
#include<cctype>
const int M=6e4+5;
int n,m,w1[M],w2[M];
inline char read_c(){
char s;while(!isalpha(s=getchar()));return s;
}
inline int read(){
int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void write(int n){
static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);putchar(10);
}
struct data{
int w[2][2];
inline int*operator[](const int&x){
return w[x];
}
}t[M<<2];
inline int min(const int&a,const int&b){
return a>b?b:a;
}
inline data Merge(data a,const int&x,const int&y,data b){
data ans;
ans[0][0]=min(a[0][1]+b[1][0]+min(x,y),min(a[0][0]+b[1][0],a[0][1]+b[0][0])+x+y);
ans[1][0]=min(a[1][1]+b[1][0]+min(x,y),min(a[1][0]+b[1][0],a[1][1]+b[0][0])+x+y);
ans[0][1]=min(a[0][1]+b[1][1]+min(x,y),min(a[0][0]+b[1][1],a[0][1]+b[0][1])+x+y);
ans[1][1]=min(a[1][1]+b[1][1]+min(x,y),min(a[1][0]+b[1][1],a[1][1]+b[0][1])+x+y);
return ans;
}
inline void update(const int&u,const int&L,const int&R){
const int&mid=L+R>>1;t[u]=Merge(t[u<<1],w1[mid],w2[mid],t[u<<1|1]);
}
inline void Build(const int&u,const int&L=1,const int&R=n){
if(L==R)return void(t[u][1][1]=read());
const int&mid=L+R>>1;Build(u<<1,L,mid);Build(u<<1|1,mid+1,R);update(u,L,R);
}
inline void Mdf(const int&u,const int&x,const int&w,const int&L=1,const int&R=n){
if(L==R)return void(t[u][1][1]=w);
const int&mid=L+R>>1;x<=mid?Mdf(u<<1,x,w,L,mid):Mdf(u<<1|1,x,w,mid+1,R);update(u,L,R);
}
inline void Update(const int&u,const int&x,const int&L=1,const int&R=n){
const int&mid=L+R>>1;if(x!=mid)x<=mid?Update(u<<1,x,L,mid):Update(u<<1|1,x,mid+1,R);update(u,L,R);
}
inline data Qry(const int&u,const int&l,const int&r,const int&L=1,const int&R=n){
if(l<=L&&R<=r)return t[u];
const int&mid=L+R>>1;if(r<=mid)return Qry(u<<1,l,r,L,mid);if(l>mid)return Qry(u<<1|1,l,r,mid+1,R);
return Merge(Qry(u<<1,l,r,L,mid),w1[mid],w2[mid],Qry(u<<1|1,l,r,mid+1,R));
}
signed main(){
n=read();m=read();for(int i=1;i<n;++i)scanf("%d",w1+i);for(int i=1;i<n;++i)scanf("%d",w2+i);Build(1);
for(int i=1;i<=m;++i){
char s=read_c();
if(s=='C'){
int x0,y0,x1,y1;x0=read();y0=read();x1=read();y1=read();
if(y0==y1)Mdf(1,y0,read());else(x0==1?w1:w2)[min(y0,y1)]=read(),Update(1,min(y0,y1));
}
if(s=='Q'){
int L,R;L=read();R=read();write(Qry(1,L,R)[1][1]);
}
}
}