[JOISC 2019 Day3]穿越时空 Bitaro

阅读: 评论:0

[JOISC 2019 Day3]穿越时空 Bitaro

[JOISC 2019 Day3]穿越时空 Bitaro

穿越时空 Bitaro

题解

首先应该很容易想到将点 i i i处的时间区间减去 i i i,这样就可以保证我们得时间前行转化成直线。
我们可以将转化后的前行的 x − t x-t x−t图画出来,很明显,我们得最优策略是先一直直走,遇到不能走时再调整到最近的第一个能走的时间。

但由于原询问要求处理代修改的情况与区间查询,我们很容易就想到了线段树。
对于每一个区间,我们可以得到一个三元组 ( L ′ , R ′ , c o s t ) (L',R',cost) (L′,R′,cost),表示时间为 L ′ L' L′时进入区间,为 R ′ R' R′时出区间,消耗为 c o s t cost cost。
对于合并三元组时,需要判断两个三元组的时间区间 ( L ′ , R ′ ) (L',R') (L′,R′)的对应关系。
若 R ′ ′ < L ′ R''<L' R′′<L′,需要停会再走,这个阶段是不会增加能量消耗的。
但对于 R ′ ′ > L ′ R''>L' R′′>L′的部分,需要向前回溯。
但由于实际操作中,开始的时间可能是一个区间,所以我们维护的其实是一个四元组。

由于开始的地方与结束的地方的大小关系是不定的,既有可能从前往后,又有可能从后往前,所以我们需要维护前缀后缀两棵线段树。

时间复杂度 O ( ( n + q ) l o g n ) Oleft((n+q)log, nright) O((n+q)logn)。

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
const int mo=1e9+7;
const int INF=0x7f7f7f7f;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int n,q;LL L[MAXN],R[MAXN];
struct tree{LL l,r,x,y;friend tree operator + (const tree &x,const tree &y){tree res;res.l=max(y.l,min(y.r,x.l));res.r=min(y.r,max(y.l,x.r));res.x=x.l<x.r?y.x>x.r?x.x:max(y.x,x.l):x.x;res.y=x.y+y.y+max(x.l-y.x,0LL);return res;}
};
struct range{LL st,ed;};
class segmentTree{private:tree tr[MAXN<<2];void updata(int rt){tr[rt]=tr[rt<<1]+tr[rt<<1|1];}public:range s[MAXN];void insert(int rt,int id){tr[rt]=(tree){s[id].st-id,s[id].ed-id-1LL,s[id].ed-id-1LL,0LL};}void build(int rt,int l,int r){if(l==r){insert(rt,l);return ;}int mid=l+r>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);updata(rt);}void modify(int rt,int l,int r,int ai,LL wl,LL wr){if(l==r){s[l]=(range){wl,wr};insert(rt,ai);return ;}int mid=l+r>>1;if(ai<=mid)modify(rt<<1,l,mid,ai,wl,wr);else modify(rt<<1|1,mid+1,r,ai,wl,wr);updata(rt);}tree query(int rt,int l,int r,int al,int ar){if(al<=l&&r<=ar)return tr[rt];int mid=l+r>>1;tree res;if(ar<=mid)return query(rt<<1,l,mid,al,ar);if(al>mid)return query(rt<<1|1,mid+1,r,al,ar);return query(rt<<1,l,mid,al,ar)+query(rt<<1|1,mid+1,r,al,ar);}LL work(int a,LL b,int c,LL d){LL res=0;b-=a;d-=c;if(a==c)return max(b-d,0LL);tree tmp=query(1,1,n-1,a,c-1);res=tmp.y+max(b-tmp.x,0LL);b=max(b,tmp.l);b=min(b,tmp.r);return res+max(b-d,0LL);}
}Pre,Suf;
signed main(){read(n);read(q);for(int i=1;i<n;i++)read(L[i]),read(R[i]),Pre.s[i]=(range){L[i],R[i]},Suf.s[n-i]=(range){L[i],R[i]};if(n>1)Pre.build(1,1,n-1),Suf.build(1,1,n-1);for(int i=1;i<=q;i++){int typ;read(typ);if(typ==1){LL p,s,e;read(p);read(s);read(e);dify(1,1,n-1,p,s,e);dify(1,1,n-1,n-p,s,e);}else{int a,c;LL b,d;read(a);read(b);read(c);read(d);if(a<c)printf("%lldn",Pre.work(a,b,c,d));else printf("%lldn",Suf.work(n-a+1,b,n-c+1,d));}}return 0;
}

谢谢!!!

本文发布于:2024-02-04 14:33:51,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170709444556404.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:Git穿梭时空
下一篇:关于穿梭时空
标签:时空   JOISC   Bitaro
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23