LOJ #3038. 「JOISC 2019 Day3」穿越时空 Bitar
不知道怎么评价这种题目。
首先这个变化的时间非常烦,因此先对于第\(i\)个点减去\(i\)就没这么多屁事。
然后左走到右还有右走到左也很烦,干脆从右往左把序列翻过来做两次就好了。
于是现在问题简化很多。我们考虑连续经过两个区间\([l_1,r_1]\)与\([l_2,r_2]\)。
如果\(\max(l_1,l_2)\leq \min(r_1,r_2)\),说明这两个区间仍然有交,因此接下来一定是走\([\max(l_1,l_2),\min(r_1,r_2)]\)这一段。
如果无交,那么就变成了要走到一个点,再从一个点走出去。可以用一个三元组\((x,y,v)\)表示走到\(x\),然后从\(y\)走出,花费\(v\)的代价。
带修的话直接上线段树维护就好了。时间复杂度\(O(n\log n)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (300000+5)
#define M (6000000+5)
#define K (1500+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define ull unsigned ll
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;const int INF=1e9+7;
int n,m,Q,A[N],B[N],Op[N],L[N],R[N],X[N],Y[N];ll Ans[N];
struct Node{
int x,y;ll v;Node operator +(const Node &B)const{
if(~v) {return ~B.v?(Node){x,B.y,max(y-B.x,0)+v+B.v}:(Node){x,min(B.y,max(B.x,y)),v+max(y-B.y,0)};}
else if(~B.v) return (Node){min(max(x,B.x),y),B.y,B.v+max(x-B.x,0)};else if(max(x,B.x)<=min(y,B.y)) return (Node){max(x,B.x),min(y,B.y),-1};
else return y<B.x?(Node){y,B.x,0}:(Node){x,B.y,x-B.y};
}
};
namespace Tree{
#define ls v<<1
#define rs v<<1|1
Node F[N<<2];I void Up(int v){F[v]=F[ls]+F[rs];}I void BD(int l=1,int r=n-1,int v=1){if(l>r) return;if(l==r) {F[v]=(Node){A[l]-l,B[l]-l-1,-1};return;}int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);Up(v);}
I void Ins(int x,int y,int z,int l=1,int r=n-1,int v=1){if(l==r){F[v]=(Node){y-l,z-l-1,-1};return;}int m=l+r>>1;x<=m?Ins(x,y,z,l,m,ls):Ins(x,y,z,m+1,r,rs);Up(v);}
I Node Qry(int x,int y,int l=1,int r=n-1,int v=1){if(x>y)return (Node){-INF,INF,-1};if(x<=l&&r<=y) return F[v];int m=l+r>>1;if(y<=m) return Qry(x,y,l,m,ls);if(x>m) return Qry(x,y,m+1,r,rs);return Qry(x,y,l,m,ls)+Qry(x,y,m+1,r,rs);}
#undef ls
#undef rs
}
I void Solve(){int i,j;Tree::BD();for(i=1;i<=m;i++) {if(Op[i]==1)Tree::Ins(X[i],L[i],R[i]);else L[i]<=R[i]&&(Ans[i]=((Node){X[i]-L[i],X[i]-L[i],-1}+Tree::Qry(L[i],R[i]-1)+(Node){Y[i]-R[i],Y[i]-R[i],-1}).v);}}
int main(){
freopen("1.in","r",stdin);
int i,j;scanf("%d%d",&n,&m);for(i=1;i<n;i++) scanf("%d%d",&A[i],&B[i]);for(i=1;i<=m;i++) scanf("%d",&Op[i]),Op[i]^1?scanf("%d%d%d%d",&L[i],&X[i],&R[i],&Y[i]):scanf("%d%d%d",&X[i],&L[i],&R[i]);
Solve();reverse(A+1,A+n);reverse(B+1,B+n);for(i=1;i<=m;i++) Op[i]^1?(L[i]=n-L[i]+1,R[i]=n-R[i]+1):(X[i]=n-X[i]);Solve();for(i=1;i<=m;i++) Op[i]^1&&(printf("%lld\n",Ans[i]));
}