• 一次函数


     思路:

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

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

      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;
    }
  • 相关阅读:
    弹性计算双周刊 第24期
    【阿里云新品发布·周刊】第8期:数字化风暴已经来临!云+区块链,如何颠覆未来科技?
    洞见数据库前沿 阿里云数据库最强阵容 DTCC 2019 八大亮点抢先看
    开发者招聘节 | 2019阿里巴巴技术面试题分享(陆续放出)
    bzoj1856: [Scoi2010]字符串
    bzoj1257: [CQOI2007]余数之和sum
    bzoj1088: [SCOI2005]扫雷Mine
    noip2015 运输计划
    noip2015 子串
    noip2015 斗地主
  • 原文地址:https://www.cnblogs.com/thmyl/p/6048368.html
Copyright © 2020-2023  润新知