#include<bits/stdc++.h>
#define re register
#define LL long long
#define min std::min
inline int read() {
char c=getchar();int x=0,r=1;
while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return r*x;
}
const int maxn=5e4+5;
const int mod=19940417;
int c[maxn][21];
int l[maxn*3],r[maxn*3],tag[maxn*3],rev[maxn*3];
int dp[maxn*3][21],h[21],pw[21],ans[21],n,m;
inline int C(int n,int m) {return m>n?0:c[n][m];}
inline void merge(int *f,int *g,int T) {
for(re int i=0;i<=T;i++) h[i]=0;
for(re int i=0;i<=T;i++)
for(re int j=0;i+j<=T;j++)
h[i+j]=(h[i+j]+1ll*f[i]*g[j]%mod)%mod;
for(re int i=0;i<=T;i++) f[i]=h[i];
}
inline void pushup(int x) {
for(re int i=0;i<=20;i++)
dp[x][i]=dp[x<<1][i];
merge(dp[x],dp[x<<1|1],20);
}
void build(int x,int y,int i) {
l[i]=x,r[i]=y;
if(x==y) {
dp[i][0]=1;dp[i][1]=(read()+mod)%mod;return;
}
int mid=x+y>>1;
build(x,mid,i<<1),build(mid+1,y,i<<1|1);
pushup(i);
}
void solve(int *f,int v,int len) {
int T=min(20,len);
for(re int i=1;i<=T;i++) pw[i]=1ll*pw[i-1]*v%mod;
for(re int i=T;i;--i)
for(re int j=i-1;j>=0;--j)
f[i]=(f[i]+1ll*f[j]*pw[i-j]%mod*C(len-j,i-j)%mod)%mod;
}
inline void pushdown(int x) {
if(rev[x]) {
rev[x<<1|1]^=1,rev[x<<1]^=1;
tag[x<<1|1]=(mod-tag[x<<1|1])%mod;
tag[x<<1]=(mod-tag[x<<1])%mod;
for(re int i=1;i<=20;i+=2)
dp[x<<1][i]=(mod-dp[x<<1][i])%mod,
dp[x<<1|1][i]=(mod-dp[x<<1|1][i])%mod;
rev[x]=0;
}
if(tag[x]) {
tag[x<<1]=(tag[x<<1]+tag[x])%mod;
tag[x<<1|1]=(tag[x<<1|1]+tag[x])%mod;
solve(dp[x<<1],tag[x],r[x<<1]-l[x<<1]+1);
solve(dp[x<<1|1],tag[x],r[x<<1|1]-l[x<<1|1]+1);
tag[x]=0;
}
}
void add(int x,int y,int v,int i) {
if(x<=l[i]&&y>=r[i]) {
solve(dp[i],v,r[i]-l[i]+1);
tag[i]=(tag[i]+v)%mod;
return;
}
pushdown(i);
int mid=l[i]+r[i]>>1;
if(x<=mid) add(x,y,v,i<<1);
if(y>mid) add(x,y,v,i<<1|1);
pushup(i);
}
void change(int x,int y,int i) {
if(x<=l[i]&&y>=r[i]) {
rev[i]^=1;
tag[i]=(mod-tag[i])%mod;
for(re int j=1;j<=20;j+=2)
dp[i][j]=(mod-dp[i][j])%mod;
return;
}
pushdown(i);
int mid=l[i]+r[i]>>1;
if(x<=mid) change(x,y,i<<1);
if(y>mid) change(x,y,i<<1|1);
pushup(i);
}
void query(int x,int y,int v,int i) {
if(x<=l[i]&&y>=r[i]) {
merge(ans,dp[i],v);
return;
}
pushdown(i);
int mid=l[i]+r[i]>>1;
if(x<=mid) query(x,y,v,i<<1);
if(y>mid) query(x,y,v,i<<1|1);
}
int main() {
n=read(),m=read();build(1,n,1);
for(re int i=0;i<=n;i++) c[i][0]=1;
for(re int i=1;i<=n;i++)
for(re int j=1;j<=min(i,20);j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
char op[4];int x,y,v;ans[0]=pw[0]=1;
while(m--) {
scanf("%s",op);x=read(),y=read();
if(op[0]=='I') {
v=read();v=(v%mod+mod)%mod;
add(x,y,v,1);
}
if(op[0]=='Q') {
v=read();v=(v%mod+mod)%mod;
for(re int i=1;i<=20;i++) ans[i]=0;
query(x,y,v,1);
printf("%d\n",ans[v]);
}
if(op[0]=='R') change(x,y,1);
}
return 0;
}
[清华集训]序列操作
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
Centos7.9 清华yum源配置
清华YUM源配置
CentOS centos -
【清华集训2014】mex
构去维护。那么离线呢,好像离线可以。以下标线段树为节点的线段树,无法判重值,好像不能维护权值,想到不能维护权值,那么就有很多数据结构不能用了,维
清华集训 mex 函数式线段树 离线大法 数据结构 -
#164. 【清华集训2015】V
DescriptionPicks博士观察完金星凌日后,设计了一个复杂的电阻器。为了简化题目
清华集训2015 V 数据结构 下传 #164 -
【NOIP2017提高A组集训10.28】序列操作
Description一开始有n个非负整数hi,接下来会进行m次操作,第i次操作给出一
NOIP 暴力 线段树 树状数组 二分