线段树与树状数组

树状数组

P3374 【模板】树状数组 1

#include <bits/stdc++.h>
using namespace std;

int n,m;
typedef long long ll;
ll tre[500001],k,a;
int opt;

ll lowbit(ll x)
{
	return (x & (-x));
}

void add(ll x,ll k)
{
	for ( ; x <= n; x += lowbit(x))
	{
		tre[x] += k;
	}
}

ll query(ll x)
{
	ll ans = 0;
	for ( ; x; x -= lowbit(x))
	{
		ans += tre[x];
	}
	return ans;
}

int main()
{
	cin >> n >> m;
	for (ll i = 1; i <= n; i++)
	{
		cin >> a;
		add(i,a);
	}
	while(m--)
	{
		cin >> opt >> a >> k;
		if(opt == 1)
		{
			add(a,k);
		}
		else
		{
			cout << query(k) - query(a - 1) << endl;
		}
	}
	return 0;
}

线段树

P3373 【模板】线段树 2
好的blog

#include <bits/stdc++.h>
using namespace std;

#define ull long long

int n,m;
ull va[400001],tag[400001],tag2[400001],sum[400001],x[400001],mo;

ull ls(int p)
{
	return (p << 1);
}

ull rs(int p)
{
	return (p << 1 | 1);
}

void pushup(int p)
{
	sum[p] = ( sum[ls(p)] + sum[rs(p)] ) % mo;
}

void f(int p,int l,int r,ull k,ull k2)
{
	sum[p] = (sum[p] * k2 ) % mo;
	sum[p] = (sum[p] + k * (r - l + 1) ) % mo;
	tag2[p] = (tag2[p] * k2) % mo;
	tag[p] = (tag[p] * k2 ) % mo;
	tag[p] = (tag[p] + k ) % mo;
}

void pushdown(int p,int l,int r)
{
	int mid = ((l + r) >> 1);
	f(ls(p),l,mid,tag[p],tag2[p]);
	f(rs(p),mid + 1,r,tag[p],tag2[p]);
	tag[p] = 0;
	tag2[p] = 1;
}

ull query(int gl,int gr,int nl,int nr,int p)
{
	ull res = 0;
	if(gl <= nl && gr >= nr)return sum[p] % mo;
	int mid = ((nr + nl) >> 1);
	pushdown(p,nl,nr);
	if(gl <= mid)res += query(gl,gr,nl,mid,ls(p));
	if(gr > mid)res += query(gl,gr,mid + 1,nr,rs(p));
	return (res % mo);
}

void add(int gl,int gr,int nl,int nr,int p,ull k,int way)
{
	if(nl >= gl && nr <= gr)
	{
		if(way)
		{
			sum[p] = (sum[p] * k) % mo;
			tag[p] = (tag[p] * k) % mo;
			tag2[p] = (tag2[p] * k) % mo;
			return ;
		}
		sum[p] = (sum[p] + k * (nr - nl + 1) ) % mo;
		tag[p] = ( tag[p] + k ) % mo;
		return ;
	}
	pushdown(p,nl,nr);
	int mid = ((nr + nl) >> 1);
	if(gl <= mid)add(gl,gr,nl,mid,ls(p),k,way);
	if(gr > mid)add(gl,gr,mid + 1,nr,rs(p),k,way);
	pushup(p);
}

void build(int p,int l,int r)
{
	tag[p] = 0;
	tag2[p] = 1;
	if(l == r)
	{
		sum[p] = x[l];
		return ;
	}
	int mid = ( (l + r) >> 1 );
	build(ls(p),l,mid);
	build(rs(p),mid+ 1,r);
	pushup(p);
}

int main()
{
	scanf(" %d %d %lld",&n,&m,&mo);
	for (int i = 1; i <= n; i++)
	{
		scanf(" %lld",&x[i]);
		x[i] %= mo;
	}	
	build(1,1,n);
	int opt;
	ull a,b,c;
	while(m--)
	{
		scanf(" %d",&opt);
		if(opt == 1)
		{
			scanf(" %lld %lld %lld",&a,&b,&c);
			add(a,b,1,n,1,(c % mo),1);
		}
		else if(opt == 2)
		{
			scanf(" %lld %lld %lld",&a,&b,&c);
			add(a,b,1,n,1,(c % mo),0);
		}
		else
		{
			scanf(" %lld %lld",&a,&b);
			//cout << "pp" << opt << "pp";
			printf("%lld\n",query(a,b,1,n,1));
		}
	}
	return 0;
}

运算优先级问题

先乘后加
lazy tag是一体的

posted @ 2022-07-13 19:57  此间无物  阅读(27)  评论(0)    收藏  举报