CF438D The Child and Sequence

题目链接:洛谷438D
知识点:线段树进阶,单点修改,区间和比较简单,重点取模(
思路,剪枝,当线段树中一区间的最大值比这个模数大的时候下层不用访问直接return;反之则一直向下访问当访问到叶子的时候更新取模。
要注意数的大小(大雾,又犯错QAQ

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
const int INF=0x3f3f3f3f;
int n,m,mx[N<<2],a[N]; //mx是区间最大值,a为叶子;
long long tr[N<<2];//区间和
void pushup(int p)
{
	mx[p]=max(mx[p<<1],mx[p<<1|1]);
	tr[p]=tr[p<<1]+tr[p<<1|1];
}
void build(int l,int r,int s)
{
	if(l==r)
	{
		mx[s] = tr[s] = a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,s<<1);
	build(mid+1,r,s<<1|1);
	pushup(s);
}
void update(int t,int x,int l,int r,int s)//单点修改;
{
	if(l==r)
	{
		mx[s]=tr[s]=x;
		return ;
	}
	int mid=(l+r)>>1;
	if(t<=mid)
		update(t,x,l,mid,s<<1); 
	else update(t,x,mid+1,r,s<<1|1);
	pushup(s);
}
void getmod(int ll,int rr,int mod,int l,int r,int s)
{
	if(mx[s]<mod)return;
	if(l==r)
	{
		tr[s]=tr[s]%mod;
		mx[s]=tr[s];
		return;
	}
	int mid=(l+r)>>1;
	if(ll<=mid)getmod(ll,rr,mod,l,mid,s<<1);  //要取模的区间是否在范围内;
	if(mid<rr)getmod(ll,rr,mod,mid+1,r,s<<1|1);
	pushup(s);
}
long long getans(int ll,int rr,int l,int r,int s){
	if(ll<=l&&rr>=r)return tr[s];
	int mid=(l+r)>>1;
	long long ans=0;
	if(ll<=mid)ans = ans+getans(ll,rr,l,mid,s<<1);
	if(rr>mid)ans = ans+getans(ll,rr,mid+1,r,s<<1|1);
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	build(1,n,1);
	while(m--)
	{
		int opt;
		scanf("%d",&opt);
		if(opt==1)
		{
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%lld\n",getans(l,r,1,n,1));
		}
		else if(opt==2)
		{
			int l,r,temp;
			scanf("%d%d%d",&l,&r,&temp);
			getmod(l,r,temp,1,n,1);
		}
		else if(opt==3)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			update(x,y,1,n,1);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值