【线段树】【BZOJ1798】【AHOI2009】维护序列

还是那个学弟@lher出的丧题之一。

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798

题意简析:就是题目啊。。。

解题思路:显然是线段树啊。。。根据乘法分配律处理一下区间乘法操作,其他就是简单的区间加法查询,很水吧owo。时间效率\(O(m \lg n) \)。

附AC代码:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
using namespace std;
struct zxy{
    ll val,mult,add;
}tr[300000];
int n,mod,q;
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void pushdown(int k,int l,int r){
    if (tr[k].mult==1&&!tr[k].add) return;
    int D=(r-l)+1;
    tr[ls].add=(tr[ls].add*tr[k].mult+tr[k].add)%mod;
    tr[rs].add=(tr[rs].add*tr[k].mult+tr[k].add)%mod;
    tr[ls].mult=(tr[ls].mult*tr[k].mult)%mod;
    tr[rs].mult=(tr[rs].mult*tr[k].mult)%mod;
    tr[ls].val=(tr[ls].val*tr[k].mult+(D-(D>>1))*tr[k].add)%mod;
    tr[rs].val=(tr[rs].val*tr[k].mult+(D>>1)*tr[k].add)%mod;
    tr[k].mult=1,tr[k].add=0;
}
inline void combine(int k){
    tr[k].val=(tr[ls].val+tr[rs].val)%mod;
}
inline void update(int k,int l,int r,int a,int b,int mult,int add){
    if (l>=a&&r<=b){
        tr[k].mult=tr[k].mult*mult%mod;
        tr[k].add=(tr[k].add*mult+add)%mod;
        tr[k].val=(tr[k].val*mult+(r-l+1)*add)%mod;
        return;
    }
    pushdown(k,l,r);
    if (a<=mid) update(ls,l,mid,a,b,mult,add);
    if (b>mid) update(rs,mid+1,r,a,b,mult,add);
    combine(k);
}
inline ll query(int k,int l,int r,int a,int b){
    if (l==a&&r==b) return tr[k].val%mod;
    pushdown(k,l,r);
    if (b<=mid) return query(ls,l,mid,a,b);
    if (a>mid) return query(rs,mid+1,r,a,b);
    return (query(ls,l,mid,a,mid)+query(rs,mid+1,r,mid+1,b))%mod;
}
inline void built(int k,int l,int r){
    tr[k].mult=1; tr[k].add=0;
    if(l==r) {
        tr[k].val=in();
        return;
    }
    built(ls,l,mid);built(rs,mid+1,r);
    combine(k);
}
int main(){
    n=in(),mod=in();    built(1,1,n);
    q=in();
    for (register int i=1; i<=q; ++i){
        int typ=in(),l=in(),r=in();
        if (typ==2) update(1,1,n,l,r,1,in());
        if (typ==1) update(1,1,n,l,r,in(),0);
        if (typ==3)printf("%lld\n",query(1,1,n,l,r));
    }
    return 0;
}

 本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

posted @ 2017-03-18 21:16  Melacau  阅读(192)  评论(0编辑  收藏  举报