码迷,mamicode.com
首页 > 其他好文 > 详细

[AHOI2009]维护序列

时间:2017-10-21 22:29:18      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:bit   代码   can   pac   its   blog   main   scanf   题目   

题解:

看到这种题目,一看就是线段树

很明显的区间线段树

加法反正不用说

乘法的时候往加法的地方也要翻倍

代码:

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=400005;
ll p,v,sum_,addv[N],mulv[N],sumv[N],a[N];
int n,m,c,x,y;
void pushdown(int o,int l,int l1,int r,int r1)
{
    sumv[o*2]=(sumv[o*2]*mulv[o]+addv[o]*(l1-l+1))%p;
    sumv[o*2+1]=(sumv[o*2+1]*mulv[o]+addv[o]*(r1-r+1))%p;
    addv[o*2]=(addv[o*2]*mulv[o]+addv[o])%p;
    addv[o*2+1]=(addv[o*2+1]*mulv[o]+addv[o])%p;
    mulv[o*2]=(mulv[o*2]*mulv[o])%p;
    mulv[o*2+1]=(mulv[o*2+1]*mulv[o])%p;
    mulv[o]=1;
    addv[o]=0;
}
void updatemul(int o,int l,int r)
{    
    if(x<=l&&r<=y)
     {
        mulv[o]=(mulv[o]*v)%p;
        addv[o]=(addv[o]*v)%p;
        sumv[o]=(sumv[o]*v)%p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)updatemul(o*2,l,mid);
    if(y>mid)updatemul(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void updateadd(int o,int l,int r)
{
    if(x<=l&&r<=y)
     {
        addv[o]=(addv[o]+v)%p;
        sumv[o]=(sumv[o]+v*(r-l+1))%p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)updateadd(o*2,l,mid);
    if(y>mid)updateadd(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void create(int o,int l,int r)
{
    addv[o]=0;
    mulv[o]=1;
    if(l==r)
     {
        sumv[o]=a[l];
        return ;
     }
    int mid=(l+r)>>1;
    create(o*2,l,mid);
    create(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
void query(int o,int l,int r)
{
    if(x<=l&&r<=y)
     {
        sum_+=sumv[o]%p;
        sum_%=p;
        return ;
     }
    int mid=(l+r)>>1;
    pushdown(o,l,mid,mid+1,r);
    if(x<=mid)query(o*2,l,mid);
    if(y>mid)query(o*2+1,mid+1,r);
    sumv[o]=(sumv[o*2]+sumv[o*2+1])%p;
}
int main()
{
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    create(1,1,n);
    scanf("%d",&m);
    while (m--)
     {
        scanf("%d%d%d",&c,&x,&y);
        if(c==1)
         {
            scanf("%d",&v);
            updatemul(1,1,n);
         }
        if(c==2)
         {
            scanf("%d",&v);
            updateadd(1,1,n);
         }
        if(c==3)
         {
            sum_=0;
            query(1,1,n);
            printf("%lld\n",sum_);
         }
     }
    return 0;
}

 

[AHOI2009]维护序列

标签:bit   代码   can   pac   its   blog   main   scanf   题目   

原文地址:http://www.cnblogs.com/xuanyiming/p/7705624.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!