你说得对,但我是宫司大人的狗!
洛谷。
上次校内模拟赛的 DS 题写分块被卡爽了,所以这集我们写线段树。
一开始半小时码出来然后一遍过样例,但一直 WA;后面怒调非常久才过。我太菜了。
分析
前两种操作就是线段树板子,所以重点考虑第三种操作。
显然,对于前两种操作,如果它们被撤销了,那我们就白做了。所以想到维护一个标记数组 \(f\),其中 \(f_i\) 表示第 \(i\) 个时刻的操作会不会被撤销。对于每个操作,如果 \(f_i\) 为真,我们就直接跳过。
同时我们发现,位置靠后的撤销操作可以撤销位置靠前的撤销操作,而位置靠前的撤销操作则不可以。于是我们可以按时刻从大到小的顺序执行所有撤销操作。对于每一次撤销操作,如果它对应的时刻已经被撤销了,那我们就跳过它;否则将它对应的区间中所有 \(f_i\) 推平为真。这一过程可以用线段树来做。
接下来就很好做了。我们使用两棵线段树,一棵维护原序列,一棵维护 \(f\)。前者先把树建出来,执行区间加、区间求最大值的操作;后者可以动态开点,执行区间推平、单点求值的操作。
于是这题就做完了。
代码
码风魔怔,欢迎来喷。
#include<iostream>
#include<vector>
#include<algorithm>
#include<bitset>
#define ll long long
using namespace std;
const int N=3e6+5;
int n,m;
int tot/*要离散化的数的总数*/;ll tott/*t 的离散化后的值域*/;
int a[N];
ll b[N<<2];
bitset<N>flag/*flag[i] -> 编号为 i 的操作有没有被撤销*/;
vector<ll>ans;
struct opt{
int op,id;
ll t,l,r,k;
}qu[N];
namespace OIfast{
char buf[1<<21],*p1,*p2,*top,buffer[1<<21];
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?0:*p1++)
#define gc getchar()
inline ll read(){
ll n=0,f=1;static char c=gc;
while(!isdigit(c)){if(c=='-')f=-1;c=gc;}
while(isdigit(c))n=(n<<3)+(n<<1)+(c^48),c=gc;
return n*f;
}
}using namespace OIfast;
namespace segmentTree{//维护原序列
#define ls u<<1
#define rs u<<1|1
#define mid (L+R>>1)
ll la[N<<2],mx[N<<2];
inline ll maxx(ll a,ll b){
return a>b?a:b;
}
inline void getmx(ll &a,ll b){
return a=maxx(a,b),void();
}
inline void pushup(int u){
return mx[u]=maxx(mx[ls],mx[rs]),void();
}
inline void pushdown(int u){
if(!la[u])return ;
return la[ls]+=la[u],la[rs]+=la[u],mx[ls]+=la[u],mx[rs]+=la[u],la[u]=0,void();
}
inline void build(int u,int L,int R){
if(L==R)return mx[u]=a[L],void();
return build(ls,L,mid),build(rs,mid+1,R),pushup(u),void();
}
inline void upd(int u,int l,int r,ll v,int L,int R){
if(L>r||l>R)return ;
if(l<=L&&R<=r)return la[u]+=v,mx[u]+=v,void();
pushdown(u);
if(l<=mid)upd(ls,l,r,v,L,mid);
if(r>mid)upd(rs,l,r,v,mid+1,R);
return pushup(u),void();
}
inline ll qry(int u,int l,int r,int L,int R){
if(L>r||l>R)return -1e18;
if(l<=L&&R<=r)return mx[u];
ll res=-1e18;pushdown(u);
if(l<=mid)getmx(res,qry(ls,l,r,L,mid));
if(r>mid)getmx(res,qry(rs,l,r,mid+1,R));
return res;
}
#undef ls
#undef rs
#undef mid
}using namespace segmentTree;
namespace SGT{//维护 f
#define mid (L+R>>1)
int idx=1;
int ls[N<<2],rs[N<<2];
bool f[N<<2];
inline void pushup(int u){
return f[u]=(f[ls[u]]&&f[rs[u]]),void();
}
inline void pushdown(int u){
if(!f[u])return ;
if(!ls[u])ls[u]=++idx;
if(!rs[u])rs[u]=++idx;
return f[ls[u]]=f[rs[u]]=1,void();
}
inline void tp(int &u,int l,int r,int L,int R){
if(!u)u=++idx;
if(L>r||l>R)return ;
if(l<=L&&R<=r)return f[u]=1,void();
pushdown(u);
if(l<=mid)tp(ls[u],l,r,L,mid);
if(r>mid)tp(rs[u],l,r,mid+1,R);
return pushup(u),void();
}
inline bool chk(int u,int tar,int L,int R){
if(!u)return 0;
if(L==R)return f[u];
if(L<=tar&&tar<=R)if(f[u])return 1;
return pushdown(u),(tar<=mid?chk(ls[u],tar,L,mid):chk(rs[u],tar,mid+1,R));
}
#undef mid
}using namespace SGT;
inline void lsh(){//离散化时间
sort(b+1,b+tot+1);tot=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=m;++i){
qu[i].t=lower_bound(b+1,b+tot+1,qu[i].t)-b;
if(qu[i].op==3){
qu[i].l=lower_bound(b+1,b+tot+1,qu[i].l)-b;
qu[i].r=lower_bound(b+1,b+tot+1,qu[i].r)-b;
}
}
return ;
}
inline void work(int i){
if(flag[qu[i].id])return ;
int op=qu[i].op;
if(op==3)return ;
int l=qu[i].l,r=qu[i].r,k=qu[i].k;
if(1==2)puts("wow");
else if(op==1)upd(1,l,r,k,1,n);
else if(op==2)ans.push_back(qry(1,l,r,1,n));
return ;
}
signed main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
build(1,1,n);
for(int i=1;i<=m;++i){
qu[i].op=read(),b[++tot]=qu[i].t=read(),qu[i].l=read(),qu[i].r=read(),qu[i].id=i;
if(qu[i].op==1)qu[i].k=read();
if(qu[i].op==3)b[++tot]=qu[i].l,b[++tot]=qu[i].r;
}
lsh();
for(int i=1;i<=m;++i)getmx(tott,qu[i].t);
sort(qu+1,qu+m+1,[](opt a,opt b){return (a.t==b.t)?(a.id<b.id):(a.t<b.t);});//按题意将操作排序
for(int i=m;i;--i){
if(qu[i].op==3){
if(chk(1,qu[i].t,1,tott))continue ;
int u=1;tp(u,qu[i].l,qu[i].r,1,tott);
}
}
for(int i=1;i<=m;++i)flag[qu[i].id]=chk(1,qu[i].t,1,tott);
for(int i=1;i<=m;++i)work(i);
printf("%d\n",ans.size());for(auto x:ans)printf("%lld\n",x);
return 0;
}

浙公网安备 33010602011771号