bzoj 2962 序列操作——线段树(卷积?)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962
如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在每个括号里选 _ 或 k ,乘起来求和。
为了算那个,枚举选了 j 个 k ;剩下那部分的乘积就是sm[cr][ i-j ]!j 和 k 可以在 len 里除了那 i-j 个位置里选,所以乘上 k^j 再乘上 C( len-(i-j) , j ) 。
调了2h+竟然只因组合数推导公式写错……
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e4+,Lm=,mod=;
int n,q,t[N],tot,c[N][Lm+],ans[Lm+],tmp[Lm+];
int ls[N<<],rs[N<<],add[N<<],sm[N<<][Lm+];
bool rev[N<<];
char ch;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return fx?ret:-ret;
}
void upd(int &x){x-=(x>=mod?mod:);}
void init()
{
c[][]=;
for(int i=;i<=n;i++)//n!
for(int j=;j<=i&&j<=Lm;j++)
{
c[i][j]=c[i-][j];
if(j)c[i][j]+=c[i-][j-],upd(c[i][j]);//i-1
}
}
void pshp(int cr,int l,int mid,int r)
{
int lm=min(r-l+,Lm),Ls=ls[cr],Rs=rs[cr];
for(int i=;i<=lm;i++)
{
sm[cr][i]=;
for(int j=;j<=i;j++)
sm[cr][i]=(sm[cr][i]+(ll)sm[Ls][j]*sm[Rs][i-j])%mod;
}
// printf("pshp l=%d r=%d\n",l,r);
// for(int i=0;i<=lm;i++)
// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);
}
void updt(int cr,int k,int len)
{
add[cr]+=k; upd(add[cr]);
int lm=min(Lm,len); for(int i=lm;i>=;i--)
for(int j=,ml=k;j<=i;j++,ml=(ll)ml*k%mod)//j=1 //j<=i not j<=lm
{
sm[cr][i]=(sm[cr][i]+(ll)sm[cr][i-j]*ml%mod*c[len-i+j][j])%mod;
// if(cr==3&&i==2)
// printf("smi=%d j=%d sm[i-j]=%d ml=%d c=[%d][%d]=%d\n",sm[cr][i],j,sm[cr][i-j],ml,len-i+j,j,c[len-i+j][j]);
} // printf("updt\n");
// for(int i=0;i<=lm;i++)
// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);
}
void updr(int cr,int lm)
{
if(add[cr])add[cr]=mod-add[cr]; rev[cr]^=;//add
for(int i=;i<=lm;i+=)
if(sm[cr][i]) sm[cr][i]=mod-sm[cr][i]; // printf("updr\n");
// for(int i=0;i<=lm;i++)
// printf(" sm[%d][%d]=%d\n",cr,i,sm[cr][i]);
}
void pshd(int cr,int l,int mid,int r)
{
int Ls=ls[cr],Rs=rs[cr];
if(rev[cr])
{
rev[cr]=;
updr(Ls,min(mid-l+,Lm));
updr(Rs,min(r-mid,Lm));
}
if(add[cr])
{
int k=add[cr]; add[cr]=;
updt(Ls,k,mid-l+); updt(Rs,k,r-mid);
}
}
void build(int l,int r,int cr)
{
if(l==r){sm[cr][]=t[l];sm[cr][]=;return;}
int mid=l+r>>;
ls[cr]=++tot; build(l,mid,ls[cr]);
rs[cr]=++tot; build(mid+,r,rs[cr]);
pshp(cr,l,mid,r);
}
void mdfy(int l,int r,int cr,int L,int R,int v)
{
if(l>=L&&r<=R)
{
// printf("mdf: cr=%d l=%d r=%d\n",cr,l,r);
updt(cr,v,r-l+); return;
}
int mid=l+r>>; pshd(cr,l,mid,r);
if(L<=mid) mdfy(l,mid,ls[cr],L,R,v);
if(mid<R) mdfy(mid+,r,rs[cr],L,R,v);
pshp(cr,l,mid,r);
}
void revs(int l,int r,int cr,int L,int R)
{
if(l>=L&&r<=R)
{
// printf("rev: cr=%d l=%d r=%d\n",cr,l,r);
updr(cr,min(r-l+,Lm));
return;
}
int mid=l+r>>; pshd(cr,l,mid,r);
if(L<=mid) revs(l,mid,ls[cr],L,R);
if(mid<R) revs(mid+,r,rs[cr],L,R);
pshp(cr,l,mid,r);
}
void query(int l,int r,int cr,int L,int R,int k)
{
if(l>=L&&r<=R)
{
int lm=min(k,r-l+);
for(int i=k;i>=;i--)
for(int j=;j<=lm&&j<=i;j++)//j<=i
ans[i]=(ans[i]+(ll)sm[cr][j]*ans[i-j])%mod;
return;
} int mid=l+r>>; pshd(cr,l,mid,r);
if(L<=mid) query(l,mid,ls[cr],L,R,k);
if(mid<R) query(mid+,r,rs[cr],L,R,k);
}
int main()
{
// freopen("data.in","r",stdin);
n=rdn(); q=rdn(); init();
for(int i=;i<=n;i++) t[i]=rdn()%mod+mod,upd(t[i]);
tot=; build(,n,); ans[]=;
for(int i=,a,b,c;i<=q;i++)
{
cin>>ch;scanf("%d%d",&a,&b);
if(ch!='R')scanf("%d",&c);
if(ch=='I')
{
c=c%mod+mod; upd(c);
mdfy(,n,,a,b,c);
}
if(ch=='R') revs(,n,,a,b);
if(ch=='Q')
{
for(int i=;i<=c;i++)ans[i]=;
query(,n,,a,b,c);
printf("%d\n",ans[c]);
}
}
return ;
}
bzoj 2962 序列操作——线段树(卷积?)的更多相关文章
- bzoj 2962 序列操作 —— 线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...
- [bzoj]2962序列操作
[bzoj]2962序列操作 标签: 线段树 题目链接 题意 给你一串序列,要你维护三个操作: 1.区间加法 2.区间取相反数 3.区间内任意选k个数相乘的积 题解 第三个操作看起来一脸懵逼啊. 其实 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- 【BZOJ-2962】序列操作 线段树 + 区间卷积
2962: 序列操作 Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 678 Solved: 246[Submit][Status][Discuss] ...
- bzoj 2962 序列操作
2962: 序列操作 Time Limit: 50 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 有一个长度为n的序列, ...
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...
- 【BZOJ2962】序列操作 线段树
[BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...
- 【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1961 Solved: 991[Submit][Status ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
随机推荐
- [Algorithm] Breadth First JavaScript Search Algorithm for Graphs
Breadth first search is a graph search algorithm that starts at one node and visits neighboring node ...
- 【Unity3D自学记录】Unity3D之自制小钟表
今天来写一个小钟表,事实上非常easy,就运用到了欧拉角. 首先创建时钟.分钟.秒钟以及4个点(12点.3点.6点.9点)偷懒了~~没弄那么多点. 时钟.分钟.秒钟这三个父级的中心一定要注意,我们旋转 ...
- GB28181对接视频流
今天抽空写下以GB28181的方式获取摄像机视频流以备后用,同时也希望能帮助到正着手开发GB28181对接视频的同学,这块的资料实在不多. 今天讲的内容不涉及到平台对接,平台对接下次有时间再讲,平台对 ...
- hibernate5(10)注解映射[2]一对多单向关联
在上一篇文章里.我们从端方向一端建立关联关系,完毕了从文章到作者的关联关系建立.但在实际的博客站点中,用户肯定还须要获取自己所写的文章,这时能够建立用户(一)对文章(多)的单向关联映射. 先来看我们的 ...
- Allegro PCB中封装焊盘替换操作详解
Allegro PCB中有些功能在某种情况下使用会产生神奇的效果,但有部分人不会或不熟悉在特定情况下使用某些功能来解决问题.如焊盘替换,有些特殊器件(如下图)封装按照datasheet给出的参考制作, ...
- JSON和JSONP 傻傻分不清楚?
什么是JSON 前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点. JSON的优点: 1.基于纯文本,跨平台传递极其简单: 2 ...
- matlab2016b -ubuntu 1604 -install- and -trouble -shooting--finally-all is ok!!
Linux系统下安装matlab2016b 标签: ubuntumatlablinux 2016-09-24 22:11 16203人阅读 评论(22) 收藏 举报 分类: linux 版权声明:本文 ...
- 嵌入式开发之cgic库---cgi库的使用
很幸运!用C语言写CGI程序还可以有比较简单的方式,那就是我们可以借助使用第三方库CGIC(CGIC是一个功能比较强大的支持CGI开发的标准C库,并支持Linux, Unix 和Windows等多操作 ...
- Android UI经常使用实例 怎样实现欢迎界面(Splash Screen)
在Android平台下.下载一个应用后,首次打开映入眼帘的便是Splash Screen,暂且不说Android的设计原则提不提倡这样的Splash Screen.先来看看一般使用Splash Scr ...
- 【Web探索之旅】第三部分第一课:server
wx_fmt=jpeg" alt="0? wx_fmt=jpeg" style="height:auto"> 内容简单介绍 .第三部分第一课:s ...