rt,比赛时口胡了一个做法:离线操作,对于最终序列,倒着读取数据,对于2操作就取区间最小值。
只需线段树的区间加和区间最小值
所以这样是正确的吗,求正确性证明||hack
AC代码:
#include <bits/stdc++.h>
#define int long long
#define root 1,1,n
#define nows now,nowl,nowr
#define lson now<<1,nowl,m
#define rson now<<1|1,m+1,nowr
//#define mid (nowl+nowr)<<1
using namespace std;
const int Maxn=300010;
struct SegMent_Tree
{
int val;
int b;
int mn;
bool nop;
int push_val;
SegMent_Tree()
{
mn=1e18;//must be <=1e18
push_val=val=b=nop=0;//don't use nop as nop&push_val because push_val might be 0
}
}z[4*Maxn];//4x space
void clear(SegMent_Tree &node)
{
node.mn=1e18;//must be <=1e18
node.push_val=node.val=node.b=node.nop=0;//don't use nop as nop&push_val because push_val might be 0
}
int a[Maxn];
inline int ls(int node) {return node<<1;}
inline int rs(int node) {return node<<1|1;}
inline SegMent_Tree operator+(const SegMent_Tree &l,const SegMent_Tree &r)
{
SegMent_Tree temp;
temp.val=(l.val+r.val);
temp.mn=min(l.mn,r.mn);
return temp;
}
void build(int now,int nowl,int nowr)
{
if(nowl==nowr)
{
z[now].mn=z[now].val=a[nowl];//pay attention to now&nowl
return;
}
int m=(nowl+nowr)>>1;
build(lson),build(rson);
z[now]=z[ls(now)]+z[rs(now)];
}
void color(int now,int nowl,int nowr,int plus)
{
z[now].val=z[now].val+(nowr-nowl+1)*plus;
z[now].b=z[now].b+plus;
z[now].mn=z[now].mn+plus;
}
void modify(int now,int nowl,int nowr,int v)
{
z[now].val=(nowr-nowl+1)*v;
z[now].b=0;//remember to clear the plus_lazytag
z[now].mn=v;
z[now].nop=1;
z[now].push_val=v;
}
void push_down(int now,int nowl,int nowr)
{
int m=(nowl+nowr)>>1;
if(z[now].nop)//preference
{
modify(lson,z[now].push_val);
modify(rson,z[now].push_val);
z[now].nop=0;
z[now].push_val=0;
}
if(z[now].b)
{
color(lson,z[now].b);
color(rson,z[now].b);
z[now].b=0;
}
}
void modify(int l,int r,int now,int nowl,int nowr,int v)
{
if(l<=nowl&&nowr<=r)
{
modify(nows,v);
return;
}
int m=(nowl+nowr)>>1;
push_down(nows);
if(l<=m) modify(l,r,lson,v);//midcut!!!!!!!!!
if(r>m) modify(l,r,rson,v);
z[now]=z[ls(now)]+z[rs(now)];
}
void update_plus(int l,int r,int now,int nowl,int nowr,int plus)
{
if(l<=nowl&&nowr<=r)
{
color(nows,plus);
return;
}
int m=(nowl+nowr)>>1;
push_down(nows);
if(l<=m) update_plus(l,r,lson,plus);
if(r>m) update_plus(l,r,rson,plus);
z[now]=z[ls(now)]+z[rs(now)];
}
SegMent_Tree query(int l,int r,int now,int nowl,int nowr)
{
if(l<=nowl&&nowr<=r)
{
return z[now];
}
int m=(nowl+nowr)>>1;
push_down(nows);
SegMent_Tree temp;
if(l<=m) temp=temp+query(l,r,lson);
if(r>m) temp=temp+query(l,r,rson);
return temp;
}
vector<int> r_ans;
int T,n,m,b,c,d,opt;
int op[Maxn],lpos[Maxn],rpos[Maxn],L[Maxn];
signed main()
{
ios::sync_with_stdio(0);
cin>>T;
while(T--)
{
r_ans.clear();
for(int i=0;i<=300000;i++) clear(z[i]);
memset(op,0,sizeof(op)),memset(lpos,0,sizeof(lpos)),memset(rpos,0,sizeof(rpos)),memset(L,0,sizeof(L));
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<m;i++)
{
cin>>op[i]>>lpos[i]>>rpos[i];
if(op[i] == 1) cin>>L[i];
}
for(int i=1;i<=n;i++) cin>>a[i];
build(root);//build build build build build!!!
for(int i=m-1;i>=0;i--)
{
opt = op[i]; b = lpos[i] , c = rpos[i];
if(opt==1)
{
d = L[i];
update_plus(b,c,root,-d);
}
else
{
r_ans.push_back(query(b,c,root).mn);
}
}
for(int i=r_ans.size()-1;i>=0;i--) cout<<r_ans[i]<<" ";
cout<<"\n";
}
}