2024.10.17 模拟赛T3 题解

题意

给定一个长度为 n 的数组 a,有 q 次操作。

  1. 1 L R x,对于 LiR,若 vi>0 则让 vi1vi,否则让 aixai

  2. 2 L R x,对于 LiR,ai0,让 ai+xai

  3. 3 h,让 vh+1vh

  4. 4 L R,查询有多少 LiR 满足 ai<0

  5. 5 L R,查询有多少 LiR 满足 ai=0

1n,m2×105

解法

开一个线段树,维护区间内有多少 ai<0,非负的最小值,非负的最小值个数三种信息。

显然可以暴力处理操作一后 ai<0 的情况。

对于 v,可以直接开 set 在操作一前找到 vi>0 的那些,直接给那些数加上 x

这样就写完了。

#include<bits/stdc++.h>
#define pb emplace_back
#define pob pop_back
#define mp make_pair
using namespace std;
typedef long long ll;
typedef __int128 LL;
const ll maxn=200007,ee=1e18,p=998244353;
ll n,q,a[maxn],vis[maxn];
set<pair<ll,ll> > st;
vector<ll> del;
struct Node{
	ll mn,cnt;
	Node operator+(Node o){
		Node res;
		if(mn==-1) res.mn=o.mn,res.cnt=o.cnt;
		else if(o.mn==-1) res.mn=mn,res.cnt=cnt;
		else if(mn==o.mn) res.mn=mn,res.cnt=cnt+o.cnt;
		else if(mn<o.mn) res.mn=mn,res.cnt=cnt;
		else res.mn=o.mn,res.cnt=o.cnt;
		return res;
	}
};
struct Tree{
	Node t[maxn<<2];
	ll val[maxn<<2],add[maxn<<2];
	void pushup(ll rt){
		val[rt]=val[rt<<1]+val[rt<<1|1];
		t[rt]=t[rt<<1]+t[rt<<1|1];
	}
	void pushdown(ll rt){
		if(!add[rt]) return;
		if(t[rt<<1].mn!=-1) t[rt<<1].mn+=add[rt];
		if(t[rt<<1|1].mn!=-1) t[rt<<1|1].mn+=add[rt];
		add[rt<<1]+=add[rt],add[rt<<1|1]+=add[rt],add[rt]=0;
	}
	void upd1(ll l,ll r,ll x,ll y,ll z,ll rt){
		if(x<=l&&r<=y){
			//cout<<l<<" "<<r<<" "<<t[rt].mn<<"\n";
			if(t[rt].mn==-1) return;
			if(l==r&&t[rt].mn<z) return val[rt]=1,t[rt]=Node{-1,0},void();
			if(t[rt].mn>=z) return t[rt].mn-=z,add[rt]-=z,void();
			if(l!=r) pushdown(rt); ll mid=(l+r)>>1;
			upd1(l,mid,x,y,z,rt<<1),upd1(mid+1,r,x,y,z,rt<<1|1);
			pushup(rt); return;
		}
		pushdown(rt); ll mid=(l+r)>>1;
		if(x<=mid) upd1(l,mid,x,y,z,rt<<1); if(mid<y) upd1(mid+1,r,x,y,z,rt<<1|1);
		pushup(rt);
	}
	void upd2(ll l,ll r,ll x,ll y,ll z,ll rt){
		if(x<=l&&r<=y) return add[rt]+=z,t[rt].mn+=z,void(); pushdown(rt); ll mid=(l+r)>>1;
		if(x<=mid) upd2(l,mid,x,y,z,rt<<1); if(mid<y) upd2(mid+1,r,x,y,z,rt<<1|1);
		pushup(rt);
	}
	void build(ll l,ll r,ll rt){
		if(l==r) return cin>>t[rt].mn,t[rt].cnt=1,void(); ll mid=(l+r)>>1;
		build(l,mid,rt<<1),build(mid+1,r,rt<<1|1),pushup(rt);
	}
	ll qry1(ll l,ll r,ll x,ll y,ll rt){
		if(x<=l&&r<=y) return val[rt]; pushdown(rt); ll mid=(l+r)>>1,res=0;
		if(x<=mid) res+=qry1(l,mid,x,y,rt<<1); if(mid<y) res+=qry1(mid+1,r,x,y,rt<<1|1);
		return res;
	}
	Node qry2(ll l,ll r,ll x,ll y,ll rt){
		if(l>r||r<x||y<l) return Node{-1,0};
		if(x<=l&&r<=y) return t[rt]; pushdown(rt); ll mid=(l+r)>>1;
		return qry2(l,mid,x,y,rt<<1)+qry2(mid+1,r,x,y,rt<<1|1);
	}
}tree;
int main(void){
	freopen("simulator.in","r",stdin);
	freopen("simulator.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n; tree.build(1,n,1);
	cin>>q;
	for(ll i=1,opt,x,y,z,tmp;i<=q;i++){
		cin>>opt>>x;
		if(opt==1){
			cin>>y>>z;
			auto it=st.lower_bound(mp(x,0));
			del.clear();
			for(;it!=st.end()&&it->first<=y;it++){
				tmp=it->first;
				tree.upd2(1,n,tmp,tmp,z,1);
				del.pb(tmp);
			}
			for(auto t:del){
				auto pir=*st.lower_bound(mp(t,0));
				st.erase(pir),vis[t]--;
				if(pir.second>1) pir.second--,st.insert(pir);
			}
			tree.upd1(1,n,x,y,z,1);
		}else if(opt==2){
			cin>>y>>z;
			tree.upd2(1,n,x,y,z,1);
		}else if(opt==3){
			if(vis[x]){
				auto pir=*st.find(mp(x,vis[x]));
				st.erase(pir); pir.second++;
				st.insert(pir);
			}else st.insert(mp(x,1));
			vis[x]++;
		}else if(opt==4){
			cin>>y;
			cout<<tree.qry1(1,n,x,y,1)<<"\n";
		}else{
			cin>>y;
			Node res=tree.qry2(1,n,x,y,1);
			if(res.mn==0) cout<<res.cnt<<"\n";
			else cout<<"0\n";
		}
	}
	return 0;
}
posted @   aeiouaoeiu  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略
点击右上角即可分享
微信分享提示