zoukankan      html  css  js  c++  java
  • 【模板】线段树(洛谷P3373)

    Description

      如题,已知一个数列,你需要进行下面三种操作:

      1.将某区间每一个数乘上(x)

      2.将某区间每一个数加上(x)

      3.求出某区间每一个数的和

    Input

      第一行包含三个整数(N)(M)(P),分别表示该数列数字的个数、操作的总个数和模数。

      第二行包含(N)个用空格分隔的整数,其中第(i)个数字表示数列第i项的初始值。

      接下来(M)行每行包含3或4个整数,表示一个操作,具体如下:

      操作1: 格式:(1 x y  k) 含义:将区间([x,y])内每个数乘上(k)

      操作2: 格式:(2  x y k) 含义:将区间([x,y])内每个数加上(k)

      操作3: 格式:(3  x  y) 含义:输出区间([x,y])内每个数的和对(P)取模所得的结果

    Output

      输出包含若干行整数,即为所有操作3的结果。

    Solution

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=100000;
    long long sum[4*N+10],multag[4*N+10],addtag[4*N+10],a[N+10];
    int n,m,Mod,opt,x,y,k;
    inline long long read()
    {
    	long long ans=0,f=1;
    	char ch=getchar();
    	while (ch<'0' || ch>'9')
    	{
    		if (ch=='-') f=-1;
    		ch=getchar();
    	}
    	while (ch>='0' && ch<='9')
    	{
    		ans=ans*10+ch-'0';
    		ch=getchar();
    	}
    	return ans*f;
    }
    long long mo(long long x,long long y)
    {
    	return x+y>=Mod?x+y-Mod:x+y;
    }
    void pushdown(int p,int l,int r)
    {
    	int mid=(l+r)>>1;
    	if (multag[p]!=1)
    	{
    		sum[p<<1]=sum[p<<1]*multag[p]%Mod;
    		sum[p<<1|1]=sum[p<<1|1]*multag[p]%Mod;
    		multag[p<<1]=multag[p<<1]*multag[p]%Mod;
    		multag[p<<1|1]=multag[p<<1|1]*multag[p]%Mod;
    		addtag[p<<1]=addtag[p<<1]*multag[p]%Mod;
    		addtag[p<<1|1]=addtag[p<<1|1]*multag[p]%Mod;
    		multag[p]=1;
    	}
    	if (addtag[p])
    	{
    		sum[p<<1]=mo(sum[p<<1],addtag[p]*(mid-l+1)%Mod);
    		sum[p<<1|1]=mo(sum[p<<1|1],addtag[p]*(r-mid)%Mod);
    		addtag[p<<1]=mo(addtag[p<<1],addtag[p]);
    		addtag[p<<1|1]=mo(addtag[p<<1|1],addtag[p]);
    		addtag[p]=0;
    	}
    }
    void build(int p,int l,int r)
    {
    	if (l==r)
    	{
    		sum[p]=a[l];
    		multag[p]=1,addtag[p]=0;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
    	multag[p]=1;addtag[p]=0;
    }
    void modify_mul(int p,int l,int r,int i,int j,long long v)
    {
    	if (l==i && r==j)
    	{
    		sum[p]=sum[p]*v%Mod;
    		multag[p]=multag[p]*v%Mod;
    		addtag[p]=addtag[p]*v%Mod;
    		return;
    	}
    	pushdown(p,l,r);
    	int mid=(l+r)>>1;
    	if (j<=mid) modify_mul(p<<1,l,mid,i,j,v);
    	else if (i>mid) modify_mul(p<<1|1,mid+1,r,i,j,v);
    	else
    	{
    		modify_mul(p<<1,l,mid,i,mid,v);
    		modify_mul(p<<1|1,mid+1,r,mid+1,j,v);
    	}
    	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
    }
    void modify_add(int p,int l,int r,int i,int j,long long v)
    {
    	if (l==i && r==j)
    	{
    		sum[p]=mo(sum[p],v*(r-l+1)%Mod);
    		addtag[p]=mo(addtag[p],v);
    		return;
    	}
    	pushdown(p,l,r);
    	int mid=(l+r)>>1;
    	if (j<=mid) modify_add(p<<1,l,mid,i,j,v);
    	else if (i>mid) modify_add(p<<1|1,mid+1,r,i,j,v);
    	else
    	{
    		modify_add(p<<1,l,mid,i,mid,v);
    		modify_add(p<<1|1,mid+1,r,mid+1,j,v);
    	}
    	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
    }
    long long query(int p,int l,int r,int i,int j)
    {
    	if (l==i && r==j) return sum[p];
    	pushdown(p,l,r);
    	int mid=(l+r)>>1;
    	if (j<=mid) return query(p<<1,l,mid,i,j);
    	else if (i>mid) return query(p<<1|1,mid+1,r,i,j);
    	else
    	{
    		return mo(query(p<<1,l,mid,i,mid),query(p<<1|1,mid+1,r,mid+1,j));
    	}
    }
    int main()
    {
    	n=read(),m=read(),Mod=read();
    	for (int i=1;i<=n;i++) a[i]=read(),a[i]%=Mod;
    	build(1,1,n);
    	while (m--)
    	{
    		opt=read();
    		if (opt==1)
    		{
    			x=read(),y=read(),k=read();
    			k%=Mod;
    			modify_mul(1,1,n,x,y,k);
    		}
    		if (opt==2)
    		{
    			x=read(),y=read(),k=read();
    			k%=Mod;
    			modify_add(1,1,n,x,y,k);
    		}
    		if (opt==3)
    		{
    			x=read(),y=read();
    			printf("%lld
    ",query(1,1,n,x,y));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    c++ stl string char* 向 string 转换的问题
    不要在疲惫中工作
    今天
    悠然自得
    忙与闲
    <转>LuaTinker的bug和缺陷
    匿名管道
    SetWindowHookEx 做消息响应
    最近工作
    实现网页页面跳转的几种方法(meta标签、js实现、php实现)
  • 原文地址:https://www.cnblogs.com/Code-Geass/p/9927318.html
Copyright © 2011-2022 走看看