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;
    }
    
    
  • 相关阅读:
    HTTP Basic 验证客户端 C#实现笔记
    泗洪高薪行业
    C#中Math的使用总结
    Android音频底层调试-基于tinyalsa
    我看项目管理第一回:认识利益相关方,提高思想意识
    【剑指Offer学习】【面试题19 :二叉树的镜像】
    算法
    zTree实现地市县三级级联DAO接口实现
    Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建
    正尝试在 OS 载入程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内执行托管代码,这样做会导致应用程序挂起。
  • 原文地址:https://www.cnblogs.com/Code-Geass/p/9927318.html
Copyright © 2011-2022 走看看