easy CodeForces - 438D (线段树区间取余)

给一个序列
支持3种操作
1 u v 对于所有i u<=i<=v,输出a[i]的和
2 u v t 对于所有i u<=i<=v a[i]=a[i]%t
3 u v 表示a[u]=v(将v赋值给a[u])
n,q<=1e5 a[i],t,v<=1e9

Input

5 5
1 2 3 4 5
2 3 5 4
3 3 5
1 2 5
2 1 3 3
1 1 3

Output

8
5

提示

对于a%=b,如果a>=b,那么a至少除以2,也就是一个数最多减小log次

取余这个操作只能每个点都操作一次去取余,但可以去剪枝,当mod大于区间最大值的时候可以直接return


#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct nomd
{
	int l,r;
	int mid(){
		return (l+r)>>1;
	}
}tree[N<<2];

ll maxn[N<<2],sum[N<<2];
void up(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
	maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
}
//void down(int rt,int m)
//{
//	if(add[rt])
//	{
//		add[rt<<1]=add[rt];
//		add[rt<<1|1]=add[rt];
//		sum[rt<<1]%=add[rt];
//		sum[rt<<1|1]%=add[rt];
//		add[rt]=0;
//	}
//}
void build(int l,int r,int rt)
{
	tree[rt].l=l;tree[rt].r=r;
	if(l==r)
	{
		scanf("%lld",&sum[rt]);
		maxn[rt]=sum[rt];
		return ;
	}
	int m=tree[rt].mid();
	build(lson);
	build(rson);
	up(rt);
}
void update1(ll c,int l,int r,int rt)
{

	if(maxn[rt]<c)
	return;
	if(tree[rt].l==tree[rt].r)//原本一直wa在这,因为用了l==r
	{
		sum[rt]%=c;
		maxn[rt]%=c;
		return;
	}

	int m=tree[rt].mid();
	if(r<=m) update1(c,l,r,rt<<1);
	else if(l>m) update1(c,l,r,rt<<1|1);
	else
	{
		update1(c,l,m,rt<<1);
		update1(c,m+1,r,rt<<1|1);
	}
	up(rt);
}
 void update2(int s, int o, ll x) {
    if(tree[o].l==tree[o].r && tree[o].l==s) {
        sum[o]=x;
        maxn[o]=x;
		return;
    }
    int mid=(tree[o].l+tree[o].r)>>1;
    if(s<=mid) update2(s,o<<1,x);
    else update2(s,o<<1|1,x);
    up(o);
}
ll query(int l,int r,int rt)
{
	if(tree[rt].l==l&&tree[rt].r==r)
	{
		return sum[rt];
	}
	int m=tree[rt].mid();
	ll res=0;
	if(r<=m) return query(l,r,rt<<1);
	else if(l>m) return query(l,r,rt<<1|1);
	else
	{
		return query(l,m,rt<<1)+query(m+1,r,rt<<1|1);
	}
	
}
int main()
{
	int n,m;
	while(~scanf("%d %d",&n,&m))
	{
		build(1,n,1);
		for(int i=0;i<m;i++)
		{
			int w;
			scanf("%d",&w);
			if(w==1)
			{
				int e, ee;
				scanf("%d %d",&e,&ee);
				printf("%lld\n",query(e,ee,1));
			}
			else if(w==3)
			{
				int e,ee;ll eee;
				scanf("%d %lld",&e,&eee);
				update2(e,1,eee);
			}
			else if(w==2)
			{
				int e,ee;ll eee;
				scanf("%d %d %lld",&e,&ee,&eee);
				update1(eee,e,ee,1);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liuliu2333/article/details/82020097
今日推荐