专栏文章

P10638 BZOJ4355 Play with sequence 题解

P10638题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipelz6g
此快照首次捕获于
2025/12/03 10:44
3 个月前
此快照最后确认于
2025/12/03 10:44
3 个月前
查看原文

前置知识

解法

将操作 11 也化成操作 22 的形式,有 aimax(ai,c)a_{i} \gets \max(a_{i}-\infty,c)
现在就转化成了区间加和区间最值,考虑使用吉司机线段树,由势能分析可知时间复杂度为 O(mlog2n)O(m \log^{2} n)。标记下传时注意遵循一定的顺序,这里的代码中规定加法标记优先级高于覆盖标记。
因保证操作过程中 ai0a_{i} \ge 0,所以只需要记录最小值出现次数即可。

代码

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
const ll inf=0x3f3f3f3f3f;
ll a[300010];
struct SMT
{
	struct SegmentTree
	{
		ll mn,se,cnt,cov,add;
	}tree[1200010];
	#define lson(rt) (rt<<1)
	#define rson(rt) (rt<<1|1)
	void pushup(ll rt)
	{
		tree[rt].mn=min(tree[lson(rt)].mn,tree[rson(rt)].mn);
		if(tree[lson(rt)].mn<tree[rson(rt)].mn)
		{
			tree[rt].se=min(tree[lson(rt)].se,tree[rson(rt)].mn);
			tree[rt].cnt=tree[lson(rt)].cnt;
		}
		if(tree[lson(rt)].mn==tree[rson(rt)].mn)
		{
			tree[rt].se=min(tree[lson(rt)].se,tree[rson(rt)].se);
			tree[rt].cnt=tree[lson(rt)].cnt+tree[rson(rt)].cnt;
		}
		if(tree[lson(rt)].mn>tree[rson(rt)].mn)
		{
			tree[rt].se=min(tree[lson(rt)].mn,tree[rson(rt)].se);
			tree[rt].cnt=tree[rson(rt)].cnt;
		}
	}
	void build(ll rt,ll l,ll r)
	{
		tree[rt].cov=-1;
		if(l==r)
		{
			tree[rt].mn=a[l];  tree[rt].se=inf;
			tree[rt].cnt=1;
			return;
		}
		ll mid=(l+r)/2;
		build(lson(rt),l,mid);  build(rson(rt),mid+1,r);
		pushup(rt);
	}
	void pushlazy(ll rt,ll add,ll cov)
	{
		tree[rt].mn+=add;
		if(tree[rt].se!=inf)  tree[rt].se+=add;
		tree[rt].add+=add;
		if(tree[rt].cov!=-1)  tree[rt].cov+=add;
		if(cov==-1||tree[rt].mn>=cov)  return;
		tree[rt].mn=tree[rt].cov=cov;
	}
	void pushdown(ll rt)
	{	
		pushlazy(lson(rt),tree[rt].add,tree[rt].cov);
		pushlazy(rson(rt),tree[rt].add,tree[rt].cov);
		tree[rt].add=0;  tree[rt].cov=-1;
	}
	void update1(ll rt,ll l,ll r,ll x,ll y,ll val)
	{
		if(x<=l&&r<=y)
		{
			pushlazy(rt,val,-1);
			return;
		}
		pushdown(rt);
		ll mid=(l+r)/2;
		if(x<=mid)  update1(lson(rt),l,mid,x,y,val);
		if(y>mid)  update1(rson(rt),mid+1,r,x,y,val);
		pushup(rt);
	}
	void update2(ll rt,ll l,ll r,ll x,ll y,ll val)
	{
		if(tree[rt].mn>=val)  return;
		if(x<=l&&r<=y&&tree[rt].se>val)
		{
			pushlazy(rt,0,val);
			return;
		}
		pushdown(rt);
		ll mid=(l+r)/2;
		if(x<=mid)  update2(lson(rt),l,mid,x,y,val);
		if(y>mid)  update2(rson(rt),mid+1,r,x,y,val);
		pushup(rt);
	}
	ll query(ll rt,ll l,ll r,ll x,ll y)
	{
		if(x<=l&&r<=y)  return (tree[rt].mn==0)*tree[rt].cnt;
		pushdown(rt);
		ll mid=(l+r)/2,ans=0;
		if(x<=mid)  ans+=query(lson(rt),l,mid,x,y);
		if(y>mid)  ans+=query(rson(rt),mid+1,r,x,y);
		return ans;
	}
}T;
int main()
{
// #define Isaac
#ifdef Isaac
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif	
	ll n,m,pd,l,r,x,i;
	cin>>n>>m;
	for(i=1;i<=n;i++)  cin>>a[i];
	T.build(1,1,n);
	for(i=1;i<=m;i++)
	{
		cin>>pd>>l>>r;
		if(pd==1)
		{
			cin>>x;
			T.update1(1,1,n,l,r,-inf);
			T.update2(1,1,n,l,r,x);
		}
		if(pd==2)
		{	
			cin>>x;
			T.update1(1,1,n,l,r,x);
			T.update2(1,1,n,l,r,0);
		}
		if(pd==3)  cout<<T.query(1,1,n,l,r)<<endl;
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...