所以求调。
给出两序列 A,B,对于 Ai,Bi 可以构造出一个函数 Fi(x)=Ai×x+Bi,现在你需要维护两种操作:
修改:输入 i,a,b,将 Ai,Bi 分别修改为 a,b。
查询:输入 l,r,x,输出 Fr(Fr−1(…Fl(x))) 的值。
思路是推一个柿子,对于两个 F 函数有:
A2×(A1×x+B1)+B2=A2×A1×x+A2×B1+B2
发现他们再次变为形如 ax+b 的形式,具有可并性,于是使用线段树维护。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,mod=1000000007;
struct node{
int k,b;
}t[N<<2],a[N];
int n,m;
//void dfs(int x,int l,int r){
// printf("%d %d %d %d %d\n",x,l,r,t[x].k,t[x].b);
// if(l==r)return;
// int mid=l+r>>1;
// dfs(x<<1,l,mid);dfs(x<<1|1,mid+1,r);
// return;
//}
int calc(int now,int x){
return t[now].k*x%mod+t[now].b%mod;
}
void pushup(int x){
t[x].k=t[x<<1].k*t[x<<1|1].k;
t[x].b=t[x<<1|1].k*t[x<<1].b+t[x<<1|1].b;
return;
}
void build(int x,int l,int r){
if(l==r){t[x]=a[l];return;}
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
pushup(x);
return;
}
void modify(int now,int l,int r,int pos,int x,int y){
if(l==r){t[now].k=x;t[now].b=y;return;}
int mid=l+r>>1;
if(mid>=pos)modify(now<<1,l,mid,pos,x,y);
else if(mid+1<=pos)modify(now<<1|1,mid+1,r,pos,x,y);
pushup(now);
return;
}
int query(int now,int l,int r,int x,int y,int z){
if(x<=l&&y>=r){return calc(now,z);}
int mid=l+r>>1,ret=0;
if(mid>=x)ret=query(now<<1,l,mid,x,y,z);
if(mid+1<=y)ret=query(now<<1|1,mid+1,r,x,y,ret?ret:z);
return ret;
}
signed main(){
freopen("function.in","r",stdin);
freopen("function.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].k,&a[i].b);
build(1,1,n);
for(int i=1;i<=m;i++){
char ch;int x,y,z;
cin>>ch;scanf("%lld%lld%lld",&x,&y,&z);
if(ch=='M'){modify(1,1,n,x,y,z);/*dfs(1,1,n);*/}
else if(ch=='Q')printf("%lld\n",query(1,1,n,x,y,z));
}
return 0;
}
样例:
input:
5 5
4 2
3 6
5 7
2 6
7 5
Q 1 5 1
Q 3 3 2
M 3 10 6
Q 1 4 3
Q 3 4 4
output:
1825
17
978
98
求教教。