Xiamen University Program Design Contest Monthly Contest D (Line segment tree: interval plus && interval multiplication)

l i n k link link

Title:

Give you an array, there are 5 operations, as follows:

  • Operation 1: Format: 1 lll r r r k k k ; Meaning: the interval[l, r] [l, r][l,r ] each hero’s attack power pluskkk
  • Operation 2: Format: 2 lll r r r k k k ; Meaning: the interval[l, r] [l, r][l,r ] each hero’s attack power multiplied bykkk
  • Operation 3: Format: 3 lll r r r k k k ; Meaning: the interval[l, r] [l, r][l,r ] the attack power of each hero is set tokkk
  • Operation 4: Format: 4 xxx ; Meaning: Add an attack power toxxafter the last herox 's hero
  • Operation 5: Format: 5 lll r r r k k k ; Meaning: output interval[l, r] [l, r][l,r ] the sum of the attack power of each hero andppp modulo

Ideas:

The single operation 1 and the single operation 2 are the basic operations of the line segment tree. The main reason is that it is a bit difficult to mix the 1, 2 operations. How to mark lazy? We set a lazy flag for add to represent addition and mul to lazy flag for multiplication.

First consider adding a lazy mark to a node:
  • Add the add mark to this node, just add it directly; add the multiplication mark, if there is an add mark in the node, then the previous add mark must be multiplied by this value, because (a + b) ∗ val = a ∗ val + b ∗ val (a+b)*val = a*val + b*vala+bval=aval+bval;
Then consider how to download:
  • Because the value of the node has been updated before the node downloads the mark, consider the download problem. First of all, add, the add of the left and right sons after the download should be equal to: add [son] ∗ mul [father] + add [father] add[son]*mul[father] + add[father]add[son]mul[father]+add[father];
  • For mul, just multiply the download directly.

I feel unclear in a few words, so let's take a look at the code.

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5+100;

ll tr[maxn * 4],add[maxn * 4],mul[maxn * 4],mod;

#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define ls o<<1
#define rs o<<1|1
#define mid (l+r)/2
void pushup(int o)
{
    
    
	tr[o] = (tr[ls] + tr[rs])%mod;
}
void down(int o,int l,int r)
{
    
    
	if(mul[o] == 1 && add[o] == 0)return ;
	tr[ls] = (tr[ls]*mul[o]%mod + add[o]*(ll)(mid-l+1)%mod) % mod;
	tr[rs] = (tr[rs]*mul[o]%mod + add[o]*(ll)(r-mid)%mod) % mod;
	add[ls] = (add[ls]*mul[o]%mod + add[o])%mod;
	add[rs] = (add[rs]*mul[o]%mod + add[o])%mod;
	mul[ls] = (mul[ls]*mul[o])%mod;
	mul[rs] = (mul[rs]*mul[o])%mod;
	mul[o] = 1,add[o] = 0;
}
void up(int o,int l,int r,int p,ll val)
{
    
    
	if(l == r)
	{
    
    
		tr[o] = val%mod;
		return ;
	}
	down(o,l,r); 
	if(p <= mid)up(lson,p,val);
	else up(rson,p,val);
	pushup(o);
}

void up_add(int o,int l,int r,int L,int R,int val)
{
    
    
	if(l >= L && r <= R)
	{
    
    
		tr[o] = (tr[o] + 1ll*(r-l+1)*val%mod) % mod;
		add[o] = (add[o] + val)%mod;
		return ;
	}
	down(o,l,r);
	if(L <= mid)up_add(lson,L,R,val);
	if(R > mid)up_add(rson,L,R,val);
	pushup(o);
}

void up_mul(int o,int l,int r,int L,int R,int val)
{
    
    
	if(l >= L && r <= R)
	{
    
    
		tr[o] = (tr[o]*(ll)val)%mod;
		add[o] = (add[o]*(ll)val)%mod;
		mul[o] = (mul[o]*(ll)val)%mod;
		return ;
	}
	down(o,l,r);
	if(L <= mid)up_mul(lson,L,R,val);
	if(R > mid)up_mul(rson,L,R,val);
	pushup(o);
}

ll qu(int o,int l,int r,int L,int R)
{
    
    
	if(l >= L && r <= R)return tr[o]%mod;
	down(o,l,r);
	ll ans = 0;
	if(L <= mid)ans = (ans + qu(lson,L,R)%mod) % mod;
	if(R > mid)ans = (ans + qu(rson,L,R)%mod) % mod;
	return ans;
}
int main()
{
    
    
	int n,m,N;
	ll x;
	scanf("%d%d%d",&n,&m,&mod);
	for(int i=1;i<=n;i++)
	{
    
    
		scanf("%lld",&x);
		up(1,1,n+m+5,i,x);
	}
	N = n;
	n = n + m + 5;
	int op,l,r,k;
	for(int i=1;i<=m;i++)
	{
    
    
		scanf("%d",&op);
		if(op == 1)
		{
    
    
			scanf("%d%d%d",&l,&r,&k);
			up_add(1,1,n,l,r,k);
		}
		else if(op == 2)
		{
    
    
			scanf("%d%d%d",&l,&r,&k);
			up_mul(1,1,n,l,r,k);
		}
		else if(op == 3)
		{
    
    
			scanf("%d%d%d",&l,&r,&k);
			up_mul(1,1,n,l,r,0);
			up_add(1,1,n,l,r,k);
		}
		else if(op == 4)
		{
    
    
			scanf("%d",&k);
			up(1,1,n,++N,k);
		}
		else if(op == 5)
		{
    
    
			scanf("%d%d",&l,&r);
			printf("%lld\n",qu(1,1,n,l,r)%mod);
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44499508/article/details/106238972