BZOJ-4499: 线性函数

[文章目录]

Description

小C最近在学习线性函数,线性函数可以表示为:f(x) = kx + b。现在小C面前有n个线性函数fi(x)=kix+bi ,他对这n个线性函数执行m次操作,每次可以:
1.M i K B 代表把第i个线性函数改为:fi(x)=kx+b 。
2.Q l r x 返回fr(fr-1(...fl(x))) mod 10^9+7 。n,m<=200000

线段树维护区间一次函数的复合。注意外层复合是右区间。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 201000 
#define mod 1000000007
struct func
{
    ll k,b;
    func(ll _k=0,ll _b=0):k(_k),b(_b){}
    func operator+(const func z) {return func(k*z.k%mod,(k*z.b+b)%mod);}
    ll calc(ll x){return (k*x+b)%mod;}
}t[N<<2];
void build(int pos,int l,int r)
{
    if(l==r)
    {
        scanf("%lld%lld",&t[pos].k,&t[pos].b);
        return ;
    }
    int mid=(l+r)>>1;
    build(pos<<1,l,mid);
    build(pos<<1|1,mid+1,r);
    t[pos]=t[pos<<1|1]+t[pos<<1];
}
void fix(int pos,int l,int r,int x,int k,int b)
{
    if(l==r)
    {
        t[pos].k=k; t[pos].b=b;
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid) fix(pos<<1,l,mid,x,k,b);
    else fix(pos<<1|1,mid+1,r,x,k,b);
    t[pos]=t[pos<<1|1]+t[pos<<1];
}
func query(int pos,int l,int r,int x,int y)
{
    if(x<=l&&y>=r) return t[pos];
    int mid=(l+r)>>1;
    if(y<=mid) return query(pos<<1,l,mid,x,y);
    else if(x>mid) return query(pos<<1|1,mid+1,r,x,y);
    else return query(pos<<1|1,mid+1,r,x,y)+query(pos<<1,l,mid,x,y);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    char sw[8]; int a,b,c;
    while(m--)
    {
        scanf("%s%d%d%d",sw,&a,&b,&c);
        if(sw[0]=='M') fix(1,1,n,a,b,c);
        else printf("%lld\n",query(1,1,n,a,b).calc(c));
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注