#include <bits/stdc++.h>
using namespace std;
using i64=long long;
using i128=__int128;
namespace DBG
{
template <class T>
void _dbg(const char *f,T t) { cerr<<f<<'='<<t<<'\n'; }
template <class A,class... B>
void _dbg(const char *f,A a,B... b)
{
while (*f!=',') cerr<<*f++;
cerr<<'='<<a<<",";
_dbg(f+1,b...);
}
template <class T>
ostream& operator << (ostream& os,const vector<T> &v)
{
os<<"[ ";
for (const auto &x:v) os<<x<<", ";
os<<"]";
return os;
}
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
}
using namespace DBG;
//发现很难做的时候要回溯
//看看在转化题意时是否漏掉条件
//记得控温
template <class T>
constexpr T power(T a,i64 b)
{
T res=1;
for (;b;b>>=1,a*=a)
if (b&1) res*=a;
return res;
}
template <int P>
struct MInt
{
int x;
constexpr MInt():x{} {}
constexpr MInt(i64 x):x{norm(x%getMod())} {}
static int Mod;
constexpr static int getMod()
{
if (P>0) return P;
else return Mod;
}
constexpr static void setMod(int Mod_) { Mod=Mod_; }
constexpr int norm(int x) const
{
if (x<0) x+=getMod();
if (x>=getMod()) x-=getMod();
return x;
}
constexpr int val() const { return x; }
explicit constexpr operator int () const { return x; }
constexpr MInt operator - () const
{
MInt res;
res.x=norm(getMod()-x);
return res;
}
constexpr MInt inv() const
{
assert(x!=0);
return power(*this,getMod()-2);
}
constexpr MInt &operator *= (MInt rhs) &
{
x=1ll*x*rhs.x%getMod();
return *this;
}
constexpr MInt &operator += (MInt rhs) &
{
x=norm(x+rhs.x);
return *this;
}
constexpr MInt &operator -= (MInt rhs) &
{
x=norm(x-rhs.x);
return *this;
}
constexpr MInt &operator /= (MInt rhs) &
{
return *this*=rhs.inv();
}
friend constexpr MInt operator * (MInt lhs,MInt rhs)
{
MInt res=lhs;
res*=rhs;
return res;
}
friend constexpr MInt operator + (MInt lhs,MInt rhs)
{
MInt res=lhs;
res+=rhs;
return res;
}
friend constexpr MInt operator - (MInt lhs,MInt rhs)
{
MInt res=lhs;
res-=rhs;
return res;
}
friend constexpr MInt operator / (MInt lhs,MInt rhs)
{
MInt res=lhs;
res/=rhs;
return res;
}
friend constexpr istream &operator >> (istream &is,MInt &a)
{
i64 v;
is>>v;
a=MInt(v);
return is;
}
friend constexpr ostream &operator << (ostream &os,const MInt &a) { return os<<a.val(); }
friend constexpr bool operator == (MInt lhs,MInt rhs) { return lhs.val()==rhs.val(); }
friend constexpr bool operator != (MInt lhs,MInt rhs) { return lhs.val()!=rhs.val(); }
};
template<>
int MInt<0>::Mod=1;
template<int V,int P>
constexpr MInt<P> CInv=MInt<P>(V).inv();
constexpr int P=998244353;
using Z=MInt<P>;
template <class Info,class Tag>
struct SGT
{
int n;
vector<Info> info;
vector<Tag> tag;
SGT():n(0) {}
SGT(int n_,Info v_=Info()) { init(n_,v_); }
template <class T>
SGT(vector<T> init_) { init(init_); }
void init(int n_,Info v_=Info()) { init(vector(n_,v_)); }
template <class T>
void init(vector<T> init_)
{
n=init_.size();
info.assign(4<<__lg(n),Info());
tag.assign(4<<__lg(n),Tag());
function<void(int,int,int)> build=[&](int p,int l,int r)
{
if (r-l==1)
{
info[p]=init_[l];
return;
}
int m=(l+r)>>1;
build(p<<1,l,m);
build(p<<1|1,m,r);
pushup(p);
};
build(1,0,n);
}
void pushup(int p) { info[p]=info[p<<1]+info[p<<1|1]; }
void apply(int p,const Tag &v)
{
info[p].apply(v);
tag[p].apply(v);
}
void pushdown(int p)
{
if (!tag[p].need) return;
apply(p<<1,tag[p]);
apply(p<<1|1,tag[p]);
tag[p]=Tag();
}
void modify(int p,int l,int r,int x,const Info &v)
{
if (r-l==1)
{
info[p]=v;
return;
}
int m=(l+r)>>1;
pushdown(p);
if (x<m) modify(p<<1,l,m,x,v);
else modify(p<<1|1,m,r,x,v);
pushup(p);
}
//O(log n)单点修改
void modify(int p,const Info &v) { modify(1,0,n,p,v); }
Info rangeQuery(int p,int l,int r,int x,int y)
{
if (l>=y||r<=x) return Info();
if (l>=x&&r<=y) return info[p];
int m=(l+r)>>1;
pushdown(p);
return rangeQuery(p<<1,l,m,x,y)+rangeQuery(p<<1|1,m,r,x,y);
}
//O(log n)区间查询[l,r)
Info rangeQuery(int l,int r) { return rangeQuery(1,0,n,l,r); }
void rangeApply(int p,int l,int r,int x,int y,const Tag &v)
{
if (l>=y||r<=x) return;
if (l>=x&&r<=y)
{
apply(p,v);
return;
}
int m=(l+r)>>1;
pushdown(p);
rangeApply(p<<1,l,m,x,y,v);
rangeApply(p<<1|1,m,r,x,y,v);
pushup(p);
}
//O(log n)区间操作[l,r)
void rangeApply(int l,int r,const Tag &v) { rangeApply(1,0,n,l,r,v); }
//O(log n)区间[l,r)内查找第一个合法位置
template <class F>
int findFirst(int p,int l,int r,int x,int y,F pred)
{
if (l>=y||r<=x||!pred(info[p])) return -1;
if (r-l==1) return l;
int m=(l+r)>>1;
pushdown(p);
int res=findFirst(p<<1,l,m,x,y,pred);
if (res==-1) res=findFirst(p<<1|1,m,r,x,y,pred);
return res;
}
template <class F>
int findFirst(int l,int r,F pred) { return findFirst(1,0,n,l,r,pred); }
template <class F>
int findLast(int p,int l,int r,int x,int y,F pred)
{
if (l>=y||r<=x||!pred(info[p])) return -1;
if (r-l==1) return l;
int m=(l+r)>>1;
pushdown(p);
int res=findLast(p<<1|1,m,r,x,y,pred);
if (res==-1) res=findLast(p<<1,l,m,x,y,pred);
return res;
}
template <class F>
int findLast(int l,int r,F pred) { return findLast(1,0,n,l,r,pred); }
};
//这里默认乘法优先 (x*a+b)*c+d=x*(a*c)+(b*c+d)
struct Tag
{
Z a=1,b=0,ia=0;
bool need=0;
void apply(Tag t)
{
if (t.need) *this=t;
}
};
struct Info
{
Z a=1,b=0;
int len=0;
void apply(Tag t)
{
if (!t.need) return;
a=power(t.a,len);
if (t.a==1) b=t.b*len;
else b=t.b*(a-1)*t.ia;
}
};
Info operator + (Info a,Info b)
{
return {a.a*b.a,a.b*b.a+b.b,a.len+b.len};
}
void R()
{
int n,q;
cin>>n>>q;
vector<Info> info(n,{0,0,1});
for (int i=0;i<n;i++)
cin>>info[i].a>>info[i].b;
SGT<Info,Tag> sgt(info);
for (int i=0;i<q;i++)
{
int op,l,r;
cin>>op>>l>>r;
if (op==0)
{
int c,d;
cin>>c>>d;
sgt.rangeApply(l,r,{c,d,c==1?0:Z(c-1).inv(),1});
}
else
{
Z x;
cin>>x;
auto res=sgt.rangeQuery(l,r);
cout<<x*res.a+res.b<<'\n';
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
// cin>>T;
while (T--) R();
return 0;
}
awa
qaq
struct tnode
{
int l, r;
ll sum;
};
struct Segment_Tree
{
tnode t[N << 2];
int mp[N];
void build(int root = 1, int l = 1, int r = n)
{
auto &u = t[root];
u.l = l, u.r = r;
if (l == r)
{
u.sum = a[l];
mp[l] = root;
return;
}
int mid = l + r >> 1;
build(root << 1, l, mid), build(root << 1 | 1, mid + 1, r);
u.sum = t[root << 1].sum + t[root << 1 | 1].sum; //push_up
}
ll query(int root, int l, int r)
{
auto &u = t[root];
if (u.l == l && u.r == r) return u.sum;
int mid = u.l + u.r >> 1;
if (r <= mid) return query(root << 1, l, r);
else if (l > mid) return query(root << 1 | 1, l, r);
else return query(root << 1, l, mid) + query(root << 1 | 1, mid + 1, r);
}
void modify(int x, ll v)
{
x = mp[x];
t[x].sum += v;
while (x >>= 1) t[x].sum = t[x << 1].sum + t[x << 1 | 1].sum;
}
};
Segment_Tree ST;
代码块指定语言就能代码高亮