BZOJ 4499 线性函数

Posted on 2017-01-15 09:51  ziliuziliu  阅读(503)  评论(1编辑  收藏  举报

SB线段树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200050
#define mod 1000000007
using namespace std;
long long n,m,x[maxn],y[maxn],tot=0,ls[maxn<<2],rs[maxn<<2],root;
long long type,a,b,c,d;
char s[2];
struct line
{
    long long k,b;
    line (long long k,long long b):k(k),b(b) {}
    line () {}
}val[maxn<<2];
line comb(line x,line y)
{
    line now;
    now.k=x.k*y.k%mod;now.b=(x.b*y.k%mod+y.b)%mod;
    return now;
}
void build(long long &now,long long left,long long right)
{
    now=++tot;
    if (left==right) 
    {
        val[now]=line(x[left],y[left]);
        return;
    }
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    val[now]=comb(val[ls[now]],val[rs[now]]);
}
void modify(long long now,long long left,long long right,long long pos,line x)
{
    if (left==right) {val[now]=x;return;}
    long long mid=(left+right)>>1;
    if (pos<=mid) modify(ls[now],left,mid,pos,x);
    else modify(rs[now],mid+1,right,pos,x);
    val[now]=comb(val[ls[now]],val[rs[now]]);
}
line ask(long long now,long long left,long long right,long long l,long long r)
{
    if ((left==l) && (right==r)) return val[now];
    long long mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r);
    else return comb(ask(ls[now],left,mid,l,mid),ask(rs[now],mid+1,right,mid+1,r));
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=n;i++) scanf("%lld%lld",&x[i],&y[i]);
    build(root,1,n);
    for (long long i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]=='M')
        {
            scanf("%lld%lld%lld",&a,&b,&c);
            modify(root,1,n,a,line(b,c));
        }
        else
        {
            scanf("%lld%lld%lld",&a,&b,&c);
            line now=ask(root,1,n,a,b);
            printf("%lld\n",(now.k*c%mod+now.b)%mod);
        }
    }
    return 0;
}