zoukankan      html  css  js  c++  java
  • P3373 【模板】线段树 2 题解

    CSDN同步

    原题链接

    前置知识:

    线段树 区间查询 / 区间修改

    简要题意:

    维护数组的区间加,乘,区间和。

    首先,如果没有乘的话,直接把 P3372 【模板】线段树1 的代码复制过来进行了。

    那么,你会说:

    • 那多简单,用两个标记,然后加的时候改加,乘的时候改乘。

    真的是这样的吗?是还用我跟你讲啊

    不是。

    比方说,一个区间原来的和是 (a).假设给它依次打上 (+2)( imes 3)(+4)( imes 5) 的标记,并用 ( ext{mul}) 表示乘法标记(初始为 (1)),( ext{add}) 表示 加法标记(初始为 (0)).

    那么,按照你说的,应该是:

    • (+2),则 ( ext{add=2,mul=1}).

    • ( imes 3),则 ( ext{add=2,mul=3}).

    好了,这里就已经错了。你 ( imes 3) 的时候,其实结果应该是:

    ((a+2) imes 3 = 3a + 6),所以你的加法标记 碰到加法是累加,碰到乘法是累乘!

    那么,计算优先级呢?当然是先乘法啦。

    因为,如果 (a imes 3 + 2) 的话,你先算加法就是 ((a+2) imes 3),然后就错了。因为你 根据乘法分配律把加法已经维护完了,最后一定是 (a imes mul + add) 的形式。

    然后,标记的下传有一些细节。

    另附一段对话(自编):

    • 线段树:唉我真是烦死了,标记要是全下传了不就不如你了吗,嗯?

    • 暴力:那怎么行,你可是 提高组算法,我是入门组算法啊,你不要下传标记就完了呗。

    • 线段树:嗯?那怎么行?

    • 暴力:没有人来询问它,你就别下传啊。等到有人询问的时候,你再下传一步,反正又不影响?

    • 线段树:真好。可两个加、乘标记混合了怎么办啊。。。

    • 暴力:你应该。。@#$^&%!$# ……*&%¥&@34%#! (cdots cdots cdots)

    • 线段树:我 (***)!!!偷懒都这么难的么。。

    • 暴力:你不难,你还是提高组算法么?看好了,这可是绿题!要是 我能解决还要你干嘛呢?是不是?

    • 线段树:行,我先脑补一下。。。

    • 暴力:要不是 CCF 老年机一秒跑不了 (10^{12}) 次,我还要你线段树????

    时间复杂度:(O(n log n)).

    实际得分:(100pts).

    //与线段树 1 相同的部分不再注释
    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    #define L (i<<1)
    #define R (i<<1)+1
    
    typedef long long ll;
    
    inline ll read(){char ch=getchar();ll f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    const ll N=1e5+1;
    ll n,m,MOD;
    
    struct node{
    	ll l,r,sum;
    	ll mul,add;
    };
    node t[4*N]; ll a[N];
    
    inline void update(ll i) {
    	t[i].sum=(t[L].sum+t[R].sum)%MOD;
    }
    
    inline void build_tree(ll i,ll l,ll r) {
    	t[i].l=l; t[i].r=r; t[i].mul=1;
    	if(l==r) {t[i].sum=a[l]%MOD;return;}
    	ll mid=(l+r)>>1;
    	build_tree(L,l,mid);
    	build_tree(R,mid+1,r);
    	update(i);
    }
    
    inline void pushdown(ll i) {
    	t[L].sum=(t[i].mul*t[L].sum+((t[L].r-t[L].l+1)*t[i].add)%MOD)%MOD;
    	t[R].sum=(t[i].mul*t[R].sum+((t[R].r-t[R].l+1)*t[i].add)%MOD)%MOD; //根据区间长度更新区间和
    	t[L].mul=(t[L].mul*t[i].mul)%MOD;
    	t[R].mul=(t[R].mul*t[i].mul)%MOD; //乘法标记累乘
    	t[L].add=(t[i].mul*t[L].add+t[i].add)%MOD;
    	t[R].add=(t[i].mul*t[R].add+t[i].add)%MOD; //加法标记先乘后加
    	t[i].mul=1; t[i].add=0; //记得甩锅
    }
    
    inline void change_add(ll i,ll l,ll r,ll k) {
    	if(l<=t[i].l && t[i].r<=r) {
    		t[i].add=(t[i].add+k)%MOD;
    		t[i].sum=(t[i].sum+k*(t[i].r-t[i].l+1))%MOD;
    		return; //更新区间和
    	} pushdown(i); update(i); 
    	ll mid=(t[i].l+t[i].r)>>1;
    	if(l<=mid) change_add(L,l,r,k);
    	if(r>mid)  change_add(R,l,r,k);
    	update(i); 
    }
    
    inline void change_mul(ll i,ll l,ll r,ll k) {
    	if(l<=t[i].l && t[i].r<=r) {
    		t[i].add=(t[i].add*k)%MOD;
    		t[i].mul=(t[i].mul*k)%MOD; //更新区间乘
    		t[i].sum=(t[i].sum*k)%MOD; return;
    	} pushdown(i); update(i);
    	ll mid=(t[i].l+t[i].r)>>1;
    	if(l<=mid) change_mul(L,l,r,k);
    	if(r>mid)  change_mul(R,l,r,k);
    	update(i);
    }
    
    inline ll querysum(ll i,ll l,ll r) {
    	if(l<=t[i].l && t[i].r<=r) return t[i].sum;
    	pushdown(i);
    	ll mid=(t[i].l+t[i].r)>>1,ans=0;
    	if(l<=mid) ans=(ans+querysum(L,l,r))%MOD;
    	if(r>mid)  ans=(ans+querysum(R,l,r))%MOD;
    	return ans; 
    }
    
    int main(){
    	n=read(),m=read(),MOD=read();
    	for(ll i=1;i<=n;i++) a[i]=read();
    	build_tree(1,1,n); while(m--) {
    		ll op=read(),x=read(),y=read(),k;
    		if(op==1) k=read(),change_mul(1,x,y,k);
    		if(op==2) k=read(),change_add(1,x,y,k);
    		if(op==3) printf("%lld
    ",querysum(1,x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Atitit.随时间变色特效 ---包厢管理系统的规划
    Atitit.request http乱码的设计防止 检测与解决最近实践p825 attilax总结.doc
    Atitit.request http乱码的设计防止 检测与解决最近实践p825 attilax总结.doc
    atitit.薄伽梵歌overview  attilax 读后感
    Atitit。 《吠陀》 《梨俱吠陀》overview 经读后感  是印度上古时期一些文献的总称
    Atitit。 《吠陀》 《梨俱吠陀》overview 经读后感  是印度上古时期一些文献的总称
    atitit.薄伽梵歌overview  attilax 读后感
    Atitit 《摩奴法典》overivew 读后感 不是由国王 颁布的,而是 僧侣编制
    Atitit 《摩奴法典》overivew 读后感 不是由国王 颁布的,而是 僧侣编制
    Atitit.执行cli cmd的原理与调试
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12631953.html
Copyright © 2011-2022 走看看