[AHOI2009]维护序列

题意

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:
(1)把数列中的一段数全部乘一个值;
(2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

\(n,m \leq 10^5\)

分析

线段树模板题,努力打一下就好了。

维护kx+b这种形式的标记是要注意:

下放标记先乘再加,乘的时候要照顾加法标记,加的时候不用管乘法标记。

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define co const
#define il inline
#pragma GCC optimize ("O3")
using namespace std;
template<class T> il T read(rg T&x)
{
    rg T data=0;
	rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+7;
int mod;

struct node
{
	int sumv;
	
	il node(rg co int&s=0):sumv(s){}
	
	il node operator+(rg const node&rhs)const
	{
		return node((sumv + rhs.sumv) % mod);
	}
};

int ql,qr,v;
struct SegTree
{
	node data[MAXN<<2];
	int addv[MAXN<<2],mulv[MAXN<<2];
#define lson (now<<1)
#define rson (now<<1|1)
	il void build(rg int now,rg int l,rg int r)
	{
		addv[now]=0,mulv[now]=1;
		if(l==r)
		{
			read(data[now].sumv);
			return;
		}
		rg int mid=(l+r)>>1;
		build(lson,l,mid);
		build(rson,mid+1,r);
		data[now]=data[lson]+data[rson];
	}
	
	il void pushdown(rg int now,rg int l,rg int r)
	{
		if(mulv[now]!=1)
		{
			data[lson].sumv = (ll) data[lson].sumv * mulv[now] % mod,
			addv[lson] = (ll) addv[lson] * mulv[now] % mod;
			mulv[lson] = (ll) mulv[lson] * mulv[now] % mod;
			data[rson].sumv = (ll) data[rson].sumv * mulv[now] % mod,
			addv[rson] = (ll) addv[rson] * mulv[now] % mod;
			mulv[rson] = (ll) mulv[rson] * mulv[now] % mod;
			mulv[now] = 1;
		}
		if(addv[now])
		{
			rg int mid=(l+r)>>1;
			(data[lson].sumv += (ll) (mid - l + 1) * addv[now] % mod ) %= mod,
			(addv[lson] += addv[now]) %= mod;
			(data[rson].sumv += (ll) (r - mid) * addv[now] % mod) %= mod,
			(addv[rson] += addv[now]) %= mod;
			addv[now]=0;
		}
	}
	
	il node query(rg int now,rg int l,rg int r)
	{
		if(ql<=l&&r<=qr)
		{
			return data[now];
		}
		pushdown(now,l,r);
		rg int mid=(l+r)>>1;
		if(qr<=mid)
			return query(lson,l,mid);
		if(ql>=mid+1)
			return query(rson,mid+1,r);
		return query(lson,l,mid)+query(rson,mid+1,r);
	}
	
	il void mul(rg int now,rg int l,rg int r)
	{
		if(ql<=l&&r<=qr)
		{
			data[now].sumv = (ll)data[now].sumv * v % mod,
			addv[now] = (ll)addv[now] * v % mod,
			mulv[now] = (ll)mulv[now] * v % mod;
			return;
		}
		pushdown(now,l,r);
		rg int mid=(l+r)>>1;
		if(ql<=mid)
			mul(lson,l,mid);
		if(qr>=mid+1)
			mul(rson,mid+1,r);
		data[now]=data[lson]+data[rson];
	}
	
	il void add(rg int now,rg int l,rg int r)
	{
		if(ql<=l&&r<=qr)
		{
			(data[now].sumv += (ll)(r - l + 1) * v % mod) %= mod,
			(addv[now] += v) %= mod;
			return;
		}
		pushdown(now,l,r);
		rg int mid=(l+r)>>1;
		if(ql<=mid)
			add(lson,l,mid);
		if(qr>=mid+1)
			add(rson,mid+1,r);
		data[now]=data[lson]+data[rson];
	}
}T;

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
	rg int n,m;
	read(n);read(mod);
	T.build(1,1,n);
	read(m);
	while(m--)
	{
		rg int opt;
		read(opt);
		if(opt==1) // mul
		{
			read(ql);read(qr);read(v);
			T.mul(1,1,n);
		}
		else if(opt==2) // add
		{
			read(ql);read(qr);read(v);
			T.add(1,1,n);
		}
		else if(opt==3)
		{
			read(ql);read(qr);
			printf("%d\n",T.query(1,1,n).sumv);
		}
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

posted on 2018-10-16 18:58  autoint  阅读(152)  评论(0编辑  收藏  举报

导航