题目链接:点击查看

题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作:

  1. 1 pos k b:将第 pos 个函数的参数变为 k 和 b
  2. 2 l r:求出 

题目分析:算半个数学问题吧,第一步是需要将题目中的公式转换一下,因为直接递归模拟肯定是要超时的,因为题目也给到了提示,就是用 l 和 r 表示下标,很容易联想到区间问题,这样操作一就是单点更新,操作二就是区间查询了,也就是需要借助线段树来实现,想到了这一步的话,还是化简一下公式吧,其实自己在纸上算两下应该就能算出来了,比较简单:

注意上面公式中的 j == r + 1时的 k_j == 1

然后就是考虑加法两边的部分分别用两个线段树来维护,方便起见我们分别表示为 tree1 和 tree2 ,现在需要考虑如何合并:

因为前半部分是累乘,所以直接累乘就好了:

tree1[ k ] = tree1[ k << 1 ] * tree1[ k << 1 | 1 ]

后半部分的话稍微麻烦一点,在纸上画一下会发现左儿子需要再乘上右儿子 tree1 的答案,也就是:

tree2[ k ] = tree2[ k << 1 ] * tree1[ k << 1 | 1 ]+ tree2[ k << 1 | 1 ]

剩下的实现就好了,两棵树维护起来比较麻烦,不过还是有技巧可寻的


2020.2.7更新:

水群的时候发现还可以用矩阵来描述转移,因为

显然可以发现对于矩阵存在转移关系,用线段树维护就好了,实现起来比区间合并简单了好多

代码:

线段树+区间合并:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;const int mod=1e9+7;int K[N],B[N];struct Node
{int l,r;LL sum;
}tree1[N<<2],tree2[N<<2];void build(int k,int l,int r)
{tree1[k].l=tree2[k].l=l;tree1[k].r=tree2[k].r=r;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void update(int k,int pos,int K,int B)
{if(tree1[k].l==tree1[k].r){tree1[k].sum=K;tree2[k].sum=B;return;}int mid=tree1[k].l+tree1[k].r>>1;if(mid>=pos)update(k<<1,pos,K,B);elseupdate(k<<1|1,pos,K,B);tree1[k].sum=tree1[k<<1].sum*tree1[k<<1|1].sum%mod;tree2[k].sum=(tree2[k<<1].sum*tree1[k<<1|1].sum%mod+tree2[k<<1|1].sum)%mod;
}pair<LL,LL> merge(pair<LL,LL> a,pair<LL,LL> b)//左半段和右半段合并
{return make_pair(a.first*b.first%mod,(a.second*b.first%mod+b.second)%mod);
}pair<LL,LL> query(int k,int l,int r)
{if(tree1[k].r<l||tree1[k].l>r)return make_pair(1,0);if(tree1[k].l>=l&&tree1[k].r<=r)return make_pair(tree1[k].sum,tree2[k].sum);return merge(query(k<<1,l,r),query(k<<1|1,l,r));
}int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);build(1,1,n);for(int i=1;i<=n;i++)scanf("%d",K+i);for(int i=1;i<=n;i++)scanf("%d",B+i);for(int i=1;i<=n;i++)update(1,i,K[i],B[i]);while(m--){int op;scanf("%d",&op);if(op==1){int pos,k,b;scanf("%d%d%d",&pos,&k,&b);update(1,pos,k,b);}else{int l,r;scanf("%d%d",&l,&r);pair<LL,LL>ans=query(1,l,r);printf("%lld\n",(ans.first+ans.second)%mod);}}return 0;
}

线段树+矩阵:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;const int mod=1e9+7;struct Ma
{LL a[2][2];Ma(){memset(a,0,sizeof(a));}static Ma ONE()//返回单位矩阵 {Ma ans;for(int i=0;i<2;i++)ans.a[i][i]=1;return ans;}friend Ma operator * (const Ma& a,const Ma& b){Ma ans;for(int i=0;i<2;i++)for(int j=0;j<2;j++){ans.a[i][j]=0;for(int k=0;k<2;k++)ans.a[i][j]+=a.a[i][k]*b.a[k][j];ans.a[i][j]%=mod;}return ans;}
};struct Node
{int l,r;Ma node;
}tree[N<<2];void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].node.a[0][1]=0;tree[k].node.a[1][1]=1;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void update(int k,int pos,int K,int B)
{if(tree[k].l==tree[k].r){tree[k].node.a[0][0]=K;tree[k].node.a[1][0]=B;return;}int mid=tree[k].l+tree[k].r>>1;if(mid>=pos)update(k<<1,pos,K,B);elseupdate(k<<1|1,pos,K,B);tree[k].node=tree[k<<1].node*tree[k<<1|1].node;
}Ma query(int k,int l,int r)
{if(tree[k].l>r||tree[k].r<l)return Ma::ONE();if(tree[k].l>=l&&tree[k].r<=r)return tree[k].node;return query(k<<1,l,r)*query(k<<1|1,l,r);
}int a[N];int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
//#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m); build(1,1,n);for(int i=1;i<=n;i++)scanf("%d",a+i);for(int i=1;i<=n;i++){int x;scanf("%d",&x);update(1,i,a[i],x);}while(m--){int op;scanf("%d",&op);if(op==1){int pos,k,b;scanf("%d%d%d",&pos,&k,&b);update(1,pos,k,b);}else{int l,r;scanf("%d%d",&l,&r);Ma ans=query(1,l,r);printf("%lld\n",(ans.a[0][0]+ans.a[1][0])%mod);}} return 0;
}

牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)相关推荐

  1. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  2. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  3. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  4. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

  5. 27.CF1004F Sonya and Bitwise OR 区间合并线段树

    27.CF1004F Sonya and Bitwise OR 区间合并线段树 个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客 给定序 ...

  6. HDU1540(线段树区间合并)

    很经典的一道题,线段树区间合并非常好的一道入门题,每个节点保存区间连续1的最大左串长度,最大右串长度,以及区间最大长度(常规的三种信息维护),更新操作时注意push_up函数,针对不同的问题,push ...

  7. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  8. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  9. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

最新文章

  1. POJ 1966 Cable TV Network【无向图点连通度 最小割 E-K算法求最大流】
  2. Uva 10177 - (2/3/4)-D Sqr/Rects/Cubes/Boxes?
  3. 分布式系统熔断机制的工作原理
  4. Python基础(10) - 异常
  5. Android 弹出对话框
  6. [剑指offer]面试题34:丑数
  7. 【LeetCode】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
  8. mysql like 数字结尾_MySQL中的Like和正则表达
  9. 国外软件测试方法,ATE软件测试方法研究及实现
  10. mysql的checkpoint
  11. 怎样用计算机画太极,用IF函数画个太极图
  12. 打开计算机出现服务器运行失败,win7打开Windows Media Player听歌提示“服务器运行失败”怎么办...
  13. shader篇-高光反射模型
  14. PS CC2017安装及破解
  15. Android手机令牌教程
  16. element输入框限制数字输入
  17. 一种解决拓展坞无法上网的方法
  18. live555峰哥的私房菜(二)-----计划任务(TaskScheduler)探讨
  19. 【PMP】启动、规划、执行、监控、收尾 五大过程组分别包括哪些管理活动
  20. 聊一聊期货反向跟单百科知识

热门文章

  1. Redis快照(Snapshot)特点
  2. 服务拆分-服务远程调用
  3. ConcurrentHashMap的源码分析-fullAddCount源码分析
  4. MyBatis 源码解读-objectFactoryElement()、objectWrapperFactoryElement()
  5. Bean生命周期配置
  6. request获得请求行的内容
  7. 数据库-笛卡尔积-内连接
  8. 数组工具类Arrays
  9. php html 文本域,html文本域标签属性有哪些?html文本域标签属性用法介绍
  10. Protobuf之proto文件编写规则