一次函数

 思路:

解决这道题需要用到线段树,通俗的说,每个父节点就是两个字结点上的函数套起来,而题目中的要求可看做单点修改和区间查询

于是问题来了,怎么建树呢。。拿出纸和笔,我们来找规律:

  f1(x) = k[1]*x+b[1]

  f2(f1(x)) = k[2]*(k[1]*x+b[1])+b[2] = k[1]*k[2]*x+k[2]*b[1]+b[2]

  f3(f2(f1(x))) = k[3]*( k[2]*(k[1]*x+b[1])+b[2]) = k[1]*k[2]*k[3]*x+k[2]*k[3]*b[1]+k[3]*b[2]+b[3]

跟着式子走,我们发现各个复合函数中的k和b其实是有一定规律的,因此建立线段树时,我们需要定义四个变量l,r,mul,sum,分别代表区间临界 和 线段树上复合函数的k和b。

可以得到父节点和子节点的关系(ans代表父节点,l,r分别代表左孩子和右孩子)

  ans.l=x.l;ans.r=y.r;
  ans.mul=x.mul*y.mul%mod;
  ans.sum=(x.sum*y.mul%mod+y.sum)%mod;

#include<iostream>
#include<cstdio>
using namespace std;
 
const int mod=1e9+7;
const int N=200005;
int n,m,K[N],b[N];
struct node
{
    int l,r;
    long long mul,sum;
}t[N<<2];
 
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
 
inline node Unite(node x,node y)
{
    node ans;
    ans.l=x.l; ans.r=y.r;
    ans.mul=x.mul*y.mul%mod;
    ans.sum=(x.sum*y.mul%mod+y.sum)%mod;
    return ans;
}
 
inline void pushup(int k)
{
    t[k]=Unite(t[k<<1],t[k<<1|1]);
}
 
void build(int k,int x,int y)
{
    if (x==y)
    {
        t[k].l=t[k].r=x;
        t[k].sum=b[x];
        t[k].mul=K[x];
        return;
    }
    int mid=x+y>>1;
    build(k<<1,x,mid); build(k<<1|1,mid+1,y);
    pushup(k);
}
 
void modify(int k,int x,int K,int B)
{
    if (t[k].l==t[k].r)
    {
        t[k].sum=B;
        t[k].mul=K;
        return;
    }
    int mid=t[k].l+t[k].r>>1;
    if (x<=mid) modify(k<<1,x,K,B); else modify(k<<1|1,x,K,B);
    pushup(k);
}
 
node query(int k,int x,int y)
{
    if (t[k].l==x&&t[k].r==y) return t[k];
    int mid=t[k].l+t[k].r>>1;
    if (y<=mid) return query(k<<1,x,y);
    else if (x>mid) return query(k<<1|1,x,y);
    else return Unite(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
}
 
int main()
{
    freopen("fx.in","r",stdin);
    freopen("fx.out","w",stdout);
     
    n=read(); m=read();
    for (int i=1;i<=n;i++)
        K[i]=read(),b[i]=read();
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        char opt[5];
        scanf("%s",opt);
        if (opt[0]=='M')
        {
            int x=read(),k=read(),b=read();
            modify(1,x,k,b);
        }
        else
        {
            int l=read(),r=read(),x=read();
            node ans=query(1,l,r);
            printf("%I64d
",(ans.mul*x%mod+ans.sum)%mod);
        }
    }
    
    fclose(stdin);
    fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/thmyl/p/7359396.html