zoukankan      html  css  js  c++  java
  • [AHOI2009]维护序列

    洛咕

    双倍经验(仅输入不同)

    题意:维护三中操作,一是区间乘,二是区间加,三是询问区间和.

    分析:在线段树的板子上增加了一个区间乘操作,但其实在洛咕还是模板题额.再开一个乘法的懒标记,初始化为1,每次遇到区间乘的操作,如果是整个区间都被包含的话,那么这个区间的乘法标记,加法标记和区间和都要更新.(pushdown)操作也是一样,三个东西都要更新.

    总之就是区间加只影响区间加和区间和两个东西,区间乘影响区间乘,区间加和区间和三个东西.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    ll n,m,mod,a[N];
    struct XD_Tree{ll l,r,add1,add2,sum;}t[N<<2];
    inline void build(int p,int l,int r){
    	t[p].l=l;t[p].r=r;t[p].add1=1;
    	if(l==r){t[p].sum=a[l];t[p].add1=1;return;}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
    	t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%mod;
    }
    inline void pushdown(int p){
    	if(t[p].add1!=1){
    //这里如果写的大于1,那么T150分,T230分,猜测数据应该是有乘负数或者乘0的
    		t[p<<1].add1=(t[p<<1].add1*t[p].add1)%mod;
    		t[p<<1|1].add1=(t[p<<1|1].add1*t[p].add1)%mod;
    		t[p<<1].add2=(t[p<<1].add2*t[p].add1)%mod;
    		t[p<<1|1].add2=(t[p<<1|1].add2*t[p].add1)%mod;
    		t[p<<1].sum=(t[p<<1].sum*t[p].add1)%mod;
    		t[p<<1|1].sum=(t[p<<1|1].sum*t[p].add1)%mod;
    		t[p].add1=1;
    	}
    	if(t[p].add2){
    		t[p<<1].add2=(t[p<<1].add2+t[p].add2)%mod;
    		t[p<<1|1].add2=(t[p<<1|1].add2+t[p].add2)%mod;
    		t[p<<1].sum=(t[p<<1].sum+1ll*t[p].add2*(t[p<<1].r-t[p<<1].l+1)%mod)%mod;
    		t[p<<1|1].sum=(t[p<<1|1].sum+1ll*t[p].add2*(t[p<<1|1].r-t[p<<1|1].l+1)%mod)%mod;
    		t[p].add2=0;
    	}
    }
    inline void change1(int p,int ql,int qr,ll val){
    	int l=t[p].l,r=t[p].r;
    	if(ql<=l&&qr>=r){
    		t[p].add1=(t[p].add1*val)%mod;
    		t[p].add2=(t[p].add2*val)%mod;
    		t[p].sum=(t[p].sum*val)%mod;
    		return;
    	}
    	pushdown(p);int mid=(l+r)>>1;
    	if(ql<=mid)change1(p<<1,ql,qr,val);
    	if(qr>mid)change1(p<<1|1,ql,qr,val);
    	t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%mod;
    }
    inline void change2(int p,int ql,int qr,ll val){
    	int l=t[p].l,r=t[p].r;
    	if(ql<=l&&qr>=r){
    		t[p].add2=(t[p].add2+val)%mod;
    		t[p].sum=(t[p].sum+1ll*(r-l+1)*val%mod)%mod;
    		return;
    	}
    	pushdown(p);int mid=(l+r)>>1;
    	if(ql<=mid)change2(p<<1,ql,qr,val);
    	if(qr>mid)change2(p<<1|1,ql,qr,val);
    	t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%mod;
    }
    inline ll query(int p,int ql,int qr){
    	int l=t[p].l,r=t[p].r;
    	if(ql<=l&&qr>=r)return t[p].sum;
    	pushdown(p);int mid=(l+r)>>1;ll cnt=0;
    	if(ql<=mid)cnt=(cnt+query(p<<1,ql,qr))%mod;
    	if(qr>mid)cnt=(cnt+query(p<<1|1,ql,qr))%mod;
    	return cnt;
    }
    int main(){
    	n=read();mod=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	build(1,1,n);m=read();
    	while(m--){
    		ll opt=read(),l=read(),r=read();
    		if(opt==1){
    			ll val=read();
    			change1(1,l,r,val);
    		}
    		else if(opt==2){
    			ll val=read();
    			change2(1,l,r,val);
    		}
    		else if(opt==3){
    			printf("%lld
    ",query(1,l,r)%mod);
    		}
    	}
        return 0;
    }
    
    
  • 相关阅读:
    dubbo+zookeeper注册服务报错问题:No service registed on zookeeper
    悲观锁和乐观锁的区别,它们是怎么实现
    cookie和session的区别,分布式环境怎么保存用户状态
    深入理解Java接口和抽象类
    Java中堆内存和栈内存详解
    Java基础梳理(一)
    Spring的@Transactional注解详细用法
    SpringBoot学习笔记(一)基础
    项目实体类使用@Data注解,但是项目业务类中使用getA(),setA()方法报错,eclipse中配置lombok
    有依赖的背包问题-购物单
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11656304.html
Copyright © 2011-2022 走看看