线段树

//线段树区间/单点加、减、乘、赋值,查询区间/单点和、最大值、最小值。
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
namespace IO
{
    const int InputBufferSize = 48*1024*1024;
    const int OutputBufferSize = 48*1024*1024;
    namespace input
    {
        char buffer[InputBufferSize],*s,*eof;
        inline void init()
        {
            s=buffer;
            eof=s+fread(buffer,1,InputBufferSize,stdin);
        }
        inline bool read(long long &x)
        {
            x=0;
            int flag=1;
            while(!isdigit(*s)&&*s!='-')
                s++;
            if(eof<=s)
                return false;
            if(*s=='-')
            {
                flag=-1;
                s++;
            }
            while(isdigit(*s))
                x=x*10+*s++-'0';
            x*=flag;
            return true;
        }
        inline bool read(int &x)
        {
            x=0;
            int flag=1;
            while(!isdigit(*s)&&*s!='-')
                s++;
            if(eof<=s)
                return false;
            if(*s=='-')
            {
                flag=-1,s++;
            }
            while(isdigit(*s))
                x=x*10+*s++-'0';
            x*=flag;
            return true;
        }
        inline bool read(char *str)
        {
            *str=0;
            while(isspace(*s))
                s++;
            if(eof<s)
                return false;
            while(!isspace(*s))
            {
                *str=0;
                *str=*s;
                str++;
                s++;
            }
            *str=0;
            return true;
        }
        inline bool read(char &ch)
        {
            ch=0;
            while(isspace(*s))
                s++;
            if(eof<s)
                return false;
            ch=0;
            ch=*s;
            s++;
            return true;
        }
    }
    namespace output
    {
        char buffer[OutputBufferSize];
        char *s=buffer;
        inline void flush()
        {
            fwrite(buffer,1,s-buffer,stdout);
            s=buffer;
        }
        inline void print(const char ch)
        {
            if(s-buffer>OutputBufferSize-2)
                flush();
            *s++=ch;
        }
        inline void print(char *str)
        {
            while(*str!=0)
                print(char(*str++));
        }
        inline void print(long long x)
        {
            char buf[25]= {0},*p=buf;
            if(x<0)
            {
                print('-');
                x=-x;
            }
            if(x==0)
                print('0');
            while(x)
            {
                *(++p)=x%10;
                x/=10;
            }
            while(p!=buf)
                print(char(*(p--)+'0'));
        }
        inline void print(int x)
        {
            char buf[25]= {0},*p=buf;
            if(x<0)
            {
                print('-');
                x=-x;
            }
            if(x==0)
                print('0');
            while(x)
            {
                *(++p)=x%10;
                x/=10;
            }
            while(p!=buf)
                print(char(*(p--)+'0'));
        }
    }
    using namespace input;
    using namespace output;
}
using namespace IO;
namespace SegmentTree
{
#define mid ((l+r)>>1)
#define lson (o<<1)
#define rson (lson|1)
    long long p;
    long long sum[800010];
    long long addv[800010];
    long long mulv[800010];
    long long Min[800010];
    long long Max[800010];
    long long chav[800010];
    bool c[800010];
    inline void push_up(int o)
    {
        sum[o]=(sum[lson]+sum[rson])%p;
        Min[o]=(min(Min[lson],Min[rson]))%p;
        Max[o]=(max(Max[lson],Max[rson]))%p;
    }
    void build(int o,int l,int r)
    {
        addv[o]=0;
        mulv[o]=1;
        chav[o]=0;
        c[o]=false;
        if(l==r)
        {
            read(sum[o]);
            Min[o]=sum[l];
            Max[o]=sum[l];
            return;
        }
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(o);
    }
    inline void push_down(int o,int l,int r,int mi,int ls,int rs)
    {
        if(c[o])
        {
            mulv[ls]=1;
            mulv[rs]=1;
            addv[ls]=0;
            addv[rs]=0;
            sum[ls]=((mi-l+1)*chav[ls])%p;
            sum[rs]=((r-mi)*chav[rs])%p;
            Min[ls]=chav[o];
            Min[rs]=chav[o];
            Max[ls]=chav[o];
            Max[rs]=chav[o];
            chav[o]=0;
            c[o]=false;
        }
        if(mulv[o]!=1)
        {
            mulv[ls]=(mulv[ls]*mulv[o])%p;
            mulv[rs]=(mulv[rs]*mulv[o])%p;
            addv[ls]=(addv[ls]*mulv[o])%p;
            addv[rs]=(addv[rs]*mulv[o])%p;
            sum[ls]=(sum[ls]*mulv[o])%p;
            sum[rs]=(sum[rs]*mulv[o])%p;
            Min[ls]=(Min[ls]*mulv[o])%p;
            Min[rs]=(Min[rs]*mulv[o])%p;
            Max[ls]=(Max[ls]*mulv[o])%p;
            Max[rs]=(Max[rs]*mulv[o])%p;
            mulv[o]=1;
        }
        if(addv[o]!=0)
        {
            addv[ls]=(addv[ls]+addv[o])%p;
            addv[rs]=(addv[rs]+addv[o])%p;
            sum[ls]=(sum[ls]+(mi-l+1)*addv[o])%p;
            sum[rs]=(sum[rs]+(r-mi)*addv[o])%p;
            Min[ls]=(Min[ls]+addv[o])%p;
            Min[rs]=(Min[rs]+addv[o])%p;
            Max[ls]=(Max[ls]+addv[o])%p;
            Max[rs]=(Max[rs]+addv[o])%p;
            addv[o]=0;
        }
    }
    void addall(int o,int l,int r,int a,int b,int x)
    {
        if(l>=a&&r<=b)
        {
            addv[o]=(addv[o]+x)%p;
            sum[o]=(sum[o]+(r-l+1)*x)%p;
            return;
        }
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            addall(lson,l,mid,a,b,x);
        if(b>mid)
            addall(rson,mid+1,r,a,b,x);
        push_up(o);
    }
    void mulall(int o,int l,int r,int a,int b,int x)
    {
        if(l>=a&&r<=b)
        {
            mulv[o]=(mulv[o]*x)%p;
            addv[o]=(addv[o]*x)%p;
            sum[o]=(sum[o]*x)%p;
            return;
        }
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            mulall(lson,l,mid,a,b,x);
        if(b>mid)
            mulall(rson,mid+1,r,a,b,x);
        push_up(o);
    }
    void chaall(int o,int l,int r,int a,int b,int x)
    {
        if(l>=a&&r<=b)
        {
            chav[o]=x%p;
            sum[o]=x*(r-l+1)%p;
            Max[o]=x%p;
            Min[o]=x%p;
            addv[o]=0;
            mulv[o]=1;
            c[o]=true;
            return;
        }
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            chaall(lson,l,mid,a,b,x);
        if(b>mid)
            chaall(rson,mid+1,r,a,b,x);
        push_up(o);
    }
    long long querySum(int o,int l,int r,int a,int b)
    {
        if(l>=a&&r<=b)
            return sum[o]%p;
        long long ans=0;
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            ans+=querySum(lson,l,mid,a,b);
        if(b>mid)
            ans+=querySum(rson,mid+1,r,a,b);
        return ans%p;
    }
    long long queryMax(int o,int l,int r,int a,int b)
    {
        if(l>=a&&r<=b)
            return Max[o]%p;
        long long ans=0;
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            ans=max(ans,queryMax(lson,l,mid,a,b));
        if(b>mid)
            ans=max(ans,queryMax(rson,mid+1,r,a,b));
        return ans%p;
    }
    long long queryMin(int o,int l,int r,int a,int b)
    {
        if(l>=a&&r<=b)
            return Min[o]%p;
        long long ans=0x7fffffffffffffff;
        push_down(o,l,r,mid,lson,rson);
        if(a<=mid)
            ans=min(ans,queryMin(lson,l,mid,a,b));
        if(b>mid)
            ans=min(ans,queryMin(rson,mid+1,r,a,b));
        return ans%p;
    }
#undef mid
#undef lson
#undef rson
}
using namespace SegmentTree;
int n,m,i,f;
int x,y;
long long k;
int main()
{
#ifdef LOCAL
    freopen("data.in","rb",stdin);
#endif
    init();
    read(n),read(m),read(p);
    build(1,1,n);
    while(m--)
    {
        read(f);
        switch(f)
        {
            case 1:
                read(x);
                read(y);
                read(k);
                mulall(1,1,n,x,y,k);
                break;
            case 2:
                read(x);
                read(y);
                read(k);
                addall(1,1,n,x,y,k);
                break;
            case 3:
                read(x);
                read(y);
                print(querySum(1,1,n,x,y)),print('\n');
                break;
            case 4:
                read(x);
                read(y);
                read(k);
                chaall(1,1,n,x,y,k);
                break;
        }
    }
    flush();
    return 0;
}

  

posted @ 2018-04-02 15:04  baka  阅读(192)  评论(0编辑  收藏  举报