J-Journey among Railway Stations
注意区间合并时是否可行信息的合并。
假设线段树当前左节点lll维护的区间是[L,mid][L,\text{mid}][L,mid],右节点维护的区间为[mid+1,R][\text{mid+1},R][mid+1,R]
如果它们分别可行,意味着可以从L→midL\to \text{mid}L→mid并且可以从mid+1→R\text{mid+1}\to Rmid+1→R即满足上述等式
uL′≤vL′,max{uL′,uL+1′}≤vL+1′,…,max{uL′,uL+1′,…,umid′}≤vmid′u_L ^{'}\leq v_{L}^{'},\max\{u_{L}^{'},u_{L+1}^{'}\} \leq v_{L+1}^{'},\dots, \max\{u_{L}^{'},u_{L+1}^{'},\dots,u_{\text{mid}}^{'}\} \leq v_{\text{mid}}^{'}uL′≤vL′,max{uL′,uL+1′}≤vL+1′,…,max{uL′,uL+1′,…,umid′}≤vmid′
umid+1′≤vmid+1′,max{umid+1′,umid+2′}≤vmid+2′,…,max{umid+1′,umid+2′,…,uR′}≤vR′u_{\text{mid+1}} ^{'}\leq v_{\text{mid+1}}^{'},\max\{u_{\text{mid+1}}^{'},u_{\text{mid+2}}^{'}\} \leq v_{\text{mid+2}}^{'},\dots, \max\{u_{\text{mid+1}}^{'},u_{\text{mid+2}}^{'},\dots,u_{\text{R}}^{'}\} \leq v_{\text{R}}^{'}umid+1′≤vmid+1′,max{umid+1′,umid+2′}≤vmid+2′,…,max{umid+1′,umid+2′,…,uR′}≤vR′
而如果我们要L→RL\to RL→R需要满足
uL′≤vL′,max{uL′,uL+1′}≤vL+1′,…,max{uL′,uL+1′,…,uR′}≤vR′u_L ^{'}\leq v_{L}^{'},\max\{u_{L}^{'},u_{L+1}^{'}\} \leq v_{L+1}^{'},\dots, \max\{u_{L}^{'},u_{L+1}^{'},\dots,u_{\text{R}}^{'}\} \leq v_{\text{R}}^{'}uL′≤vL′,max{uL′,uL+1′}≤vL+1′,…,max{uL′,uL+1′,…,uR′}≤vR′
还需要验证是否max{uL′,uL+1′,…,umid′}≤{vmid+1′,vmid+2′,…,vR′}\max\{u_{L}^{'},u_{L+1}^{'},\dots,u_{\text{mid}}^{'}\}\leq\{v_{\text{mid+1}}^{'},v_{\text{mid+2}}^{'},\dots,v_{\text{R}}^{'}\}max{uL′,uL+1′,…,umid′}≤{vmid+1′,vmid+2′,…,vR′}
即只需验证
max{uL′,uL+1′,…,umid′}≤min{vmid+1′,vmid+2′,…,vR′}\max\{u_{L}^{'},u_{L+1}^{'},\dots,u_{\text{mid}}^{'}\}\leq\min\{v_{\text{mid+1}}^{'},v_{\text{mid+2}}^{'},\dots,v_{\text{R}}^{'}\}max{uL′,uL+1′,…,umid′}≤min{vmid+1′,vmid+2′,…,vR′}
因此我们线段树维护区间maxu和minv即可合并是否能够到达的信息。
Code1
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=1000010;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll U[N],V[N],d[N],sum[N];
int n,m;
struct node
{int l,r;ll maxu,minv,tag;bool ok;
}tree[N<<2];
void pushup(node &u,node &l,node &r)
{u.maxu=max(l.maxu,r.maxu);u.minv=min(l.minv,r.minv);u.ok=(l.ok&&r.ok);if(l.maxu>r.minv) u.ok=0;
}
void build(int u,int l,int r)
{tree[u]={l,r};if(l==r){tree[u].maxu=U[l]+sum[l];tree[u].minv=V[l]+sum[l];tree[u].ok=1;return;}int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(tree[u],tree[u<<1],tree[u<<1|1]);
}
void pushdown(int u)
{if(!tree[u].tag) return;tree[u<<1].maxu+=tree[u].tag;tree[u<<1].minv+=tree[u].tag;tree[u<<1].tag+=tree[u].tag;tree[u<<1|1].maxu+=tree[u].tag;tree[u<<1|1].minv+=tree[u].tag;tree[u<<1|1].tag+=tree[u].tag;tree[u].tag=0;
}
void update(int u,int l,int r,int v)
{if(l<=tree[u].l&&tree[u].r<=r){tree[u].maxu+=v;tree[u].minv+=v;tree[u].tag+=v;return;}pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(l<=mid)update(u<<1,l,r,v);if(r>mid)update(u<<1|1,l,r,v);pushup(tree[u],tree[u<<1],tree[u<<1|1]);
}
void modify(int u,int k,int p,int q)
{if(tree[u].l==tree[u].r){tree[u].maxu+=p;tree[u].minv+=q;return;}pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(k<=mid) modify(u<<1,k,p,q);elsemodify(u<<1|1,k,p,q);pushup(tree[u],tree[u<<1],tree[u<<1|1]);
}node query(int u,int l,int r)
{if(l<=tree[u].l&&tree[u].r<=r) return tree[u];pushdown(u);int mid=tree[u].l+tree[u].r>>1;node v,vl,vr;vl={0,0,-INF,INF,0,1};vr={0,0,-INF,INF,0,1};if(l<=mid)vl=query(u<<1,l,r);if(r>mid)vr=query(u<<1|1,l,r);pushup(v,vl,vr);return v;
}
int main()
{int Tc=rd();while(Tc--){n=rd();for(int i=1;i<=n;i++) U[i]=rd<ll>();for(int i=1;i<=n;i++) V[i]=rd<ll>();for(int i=1;i<n;i++) d[i]=rd<ll>();sum[n]=0;for(int i=n-1;i>=1;i--) sum[i]=sum[i+1]+d[i];build(1,1,n);m=rd();while(m--){int op=rd();if(op==0){int l=rd(),r=rd();if(query(1,l,r).ok) puts("Yes");elseputs("No");}else if(op==1){int k=rd(),w=rd();update(1,1,k,w-d[k]);d[k]=w;}else{int k=rd(),p=rd(),q=rd();modify(1,k,p-U[k],q-V[k]);U[k]=p,V[k]=q;}}}return 0;
}
Code2
讲题人那个定义函数的做法待补~