直接线段数维护每个一次函数域就好了(不说废话,贴出代码)
/**************************************************************
Problem: 4499
User: wnjxyk
Language: C++
Result: Accepted
Time:5916 ms
Memory:28156 kb
****************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long ll;
struct V{
ll k, b;
V(){};
};
struct point{
V p;
ll ls,rs,l,r;
}a[500000];
const ll mod=1000000007;
ll cnt=1,n,b[220200][2],m,l,r,x,ck,cb,cp,rk,rb;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
V operator + (const V x,const V y){
V r;
r.k=(x.k*y.k)%mod;
r.b=(x.b*y.k+y.b)%mod;
return r;
}
void build(int l,int r,int p){
a[p].p.k=a[p].p.b=0;
a[p].l=l;a[p].r=r;
if (l==r){
a[p].p.b=b[l][1];
a[p].p.k=b[l][0];
return;
}
a[p].ls=++cnt;
build(l,(l+r)>>1,cnt);
a[p].rs=++cnt;
build(((l+r)>>1)+1,r,cnt);
a[p].p=a[a[p].ls].p+a[a[p].rs].p;
}
V query(int l,int r,int p){
if (a[p].l==l && a[p].r==r){
return a[p].p;
}
int m=(a[p].l+a[p].r)>>1;
if (l>m){
return query(l,r,a[p].rs);
}
else if (r<=m){
return query(l,r,a[p].ls);
}
else{
return query(l,m,a[p].ls)+query(m+1,r,a[p].rs);
}
}
void update (int l,int p){
if (a[p].l==l && a[p].r==l){
a[p].p.k=ck;
a[p].p.b=cb;
return;
}
int m=(a[p].l+a[p].r)>>1;
if (l>m) update(l,a[p].rs); else update(l,a[p].ls);
a[p].p=a[a[p].ls].p+a[a[p].rs].p;
}
ll getnum(V a,ll x){
return (a.k*x+a.b)%mod;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
b[i][0]=read();b[i][1]=read();
b[i][0]%=mod;
b[i][1]%=mod;
}
build(1,n,1);
char ch[10];
V ans;
for(int i=1;i<=m;i++){
scanf("%s",ch);
if (ch[0]=='Q'){
l=read();r=read();x=read();
ans=query(l,r,1);
printf("%d\n",getnum(ans,x));
}
if (ch[0]=='M'){
cp=read();ck=read();cb=read();
ck%=mod;
cb%=mod;
update(cp,1);
}
}
}