因为两个一次函数套起来也是一个一次函数
所以可以两两合并
就可以用线段树解决啦!
代码如下:
#include<ctype.h>
#include<cstdio>
#define MOD 1000000007
#define N 200200
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
typedef long long LL;
struct Data{
LL k,b;
Data operator + (const Data p) const{
Data tmp;
tmp.k=k*p.k%MOD;tmp.b=(b*p.k%MOD+p.b)%MOD;
return tmp;
}
}a[N],t;
int n,m,x,y,k;
char c[5];
struct Node{
Node *ls,*rs;
Data x;
int l,r;
Node():ls(NULL),rs(NULL){}
inline void maintain(){
x=ls->x+rs->x;
return;
}
}*root;
void maketree(int l,int r,Node *&k){
k=new Node;
k->l=l;k->r=r;
if(l==r){
k->x=a[l];
return;
}
int mid=(l+r)>>1;
maketree(l,mid,k->ls);maketree(mid+1,r,k->rs);
k->maintain();
return;
}
void Modify(int x,Data v,Node *k){
if(k->l==k->r){
k->x=v;
return;
}
int mid=(k->l+k->r)>>1;
if(x<=mid) Modify(x,v,k->ls);
else Modify(x,v,k->rs);
k->maintain();
return;
}
Data Query(int x,int y,Node *k){
if(k->l>=x && k->r<=y){
return k->x;
}
int mid=(k->l+k->r)>>1;
if(y<=mid) return Query(x,y,k->ls);
else if(x>mid) return Query(x,y,k->rs);
else return Query(x,y,k->ls)+Query(x,y,k->rs);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i].k=read();a[i].b=read();
}
maketree(1,n,root);
for(int i=1;i<=m;i++){
scanf("%s",c+1);
x=read();y=read();k=read();
if(c[1]=='M'){
t.k=y;t.b=k;
Modify(x,t,root);
}
else{
t=Query(x,y,root);
printf("%lld\n",(t.k*k%MOD+t.b)%MOD);
}
}
return 0;
}