bzoj2962 序列操作 线段树
来源:互联网 发布:筑业标书制作软件 编辑:程序博客网 时间:2024/06/09 14:26
题意:一段序列,三种操作:
1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这一段区间中选择c个数相乘的所有方案的和mod 19940417的值。
一开始没看到k<=20,觉得不可做,后来一看,哦这不就水了很多了。。
操作3的话维护f[i]表示当前区间选择i个的答案,那么n^2更新,明显有:
取负也很简单,只有奇数的时候才会有影响。
问题就是区间加有些难以处理。
假设加上x,区间长度为len,那么就是类似于
那么我们枚举x有j个,答案就是
后面那个组合数应该挺好理解,i-j个数字被确定,剩下的len-i+j个中选出j个x。
3000多B让我有点爽。。
#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=50005;const int mo=19940417;typedef long long ll;int n,m;struct node{ int l,r,lazy1,lazy2; ll f[21];;}t[N*5]; int a[N];int c[N][30];inline void update(int x){ fo(i,0,20) { t[x].f[i]=0; fo(j,0,i)t[x].f[i]=(t[x].f[i]+t[x<<1].f[j]*t[x<<1|1].f[i-j])%mo; }}inline void push1(int x){ for(int i=1;i<=20;i+=2)t[x].f[i]*=-1;}inline void push2(int x,int l,int r,int v){ int len=r-l+1; fd(i,min(len,20),1) { ll tmp=0;int mi=1; fo(j,0,i)tmp=(tmp+1ll*mi*t[x].f[i-j]%mo*c[len-i+j][j])%mo,mi=1ll*mi*v%mo; t[x].f[i]=tmp; }}inline void build(int x,int l,int r){ t[x].l=l,t[x].r=r;t[x].lazy1=1; if (l==r) { t[x].f[1]=a[l]; t[x].f[0]=1; return; } int mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); update(x);}inline void pushdown(int x,int l,int r){ if (l==r)return; int mid=(l+r)>>1,w=t[x].lazy2; if (t[x].lazy1==-1) { push1(x<<1),push1(x<<1|1); t[x<<1].lazy1*=-1,t[x<<1|1].lazy1*=-1; t[x<<1].lazy2*=-1,t[x<<1|1].lazy2*=-1; t[x].lazy1=1; } if (w) { push2(x<<1,l,mid,w),push2(x<<1|1,mid+1,r,w); t[x<<1].lazy2=(t[x<<1].lazy2+w)%mo; t[x<<1|1].lazy2=(t[x<<1|1].lazy2+w)%mo; t[x].lazy2=0; }}inline void add(int x,int l,int r,int v){ if (l>r)return; pushdown(x,t[x].l,t[x].r); if (t[x].l==l&&t[x].r==r) { push2(x,t[x].l,t[x].r,v); t[x].lazy2=(t[x].lazy2+v)%mo; return; } int mid=(t[x].l+t[x].r)>>1; add(x<<1,l,min(r,mid),v); add(x<<1|1,max(l,mid+1),r,v); update(x);}inline void oppo(int x,int l,int r){ if (l>r)return; pushdown(x,t[x].l,t[x].r); if (t[x].l==l&&t[x].r==r) { push1(x); t[x].lazy1*=-1; return; } int mid=(t[x].l+t[x].r)>>1; oppo(x<<1,l,min(r,mid)); oppo(x<<1|1,max(l,mid+1),r); update(x);}inline node query(int x,int l,int r,int v){ pushdown(x,t[x].l,t[x].r); if (t[x].l==l&&t[x].r==r)return t[x]; int mid=(t[x].l+t[x].r)>>1; if (r<=mid)return query(x<<1,l,r,v); else if (l>mid)return query(x<<1|1,l,r,v); else { node a=query(x<<1,l,mid,v), b=query(x<<1|1,mid+1,r,v),ans; fo(i,0,v) { ans.f[i]=0; fo(j,0,i) ans.f[i]=(ans.f[i]+a.f[j]*b.f[i-j]%mo)%mo; } return ans; }}int main(){ scanf("%d%d",&n,&m); fo(i,1,n)scanf("%d",&a[i]); build(1,1,n); c[0][0]=1; fo(i,1,n) { c[i][0]=1; fo(j,1,20) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo; } fo(i,1,m) { char ch[2]; int l,r,v; scanf("%s",ch); if (ch[0]=='I')scanf("%d%d%d",&l,&r,&v),add(1,l,r,v%mo); else if (ch[0]=='R')scanf("%d%d",&l,&r),oppo(1,l,r); else { scanf("%d%d%d",&l,&r,&v); node x=query(1,l,r,v); printf("%lld\n",(x.f[v]+mo)%mo); } } return 0;}
阅读全文
0 0
- 【bzoj2962】【序列操作】【线段树】
- bzoj2962 序列操作 线段树
- [BZOJ2962]序列操作(线段树)
- bzoj2962: 序列操作
- [bzoj2962]序列操作
- BZOJ2962 序列操作
- BZOJ2962: 序列操作
- bzoj2962: 序列操作
- bzoj2962 序列操作
- 【线段树】序列操作
- 【SCOI2010】【线段树】序列操作
- bzoj1858序列操作 线段树
- 【SCOI2010】序列操作 线段树
- 序列操作(线段树)
- BZOJ 1858 SCOI2010 序列操作 线段树
- 【BZOJ1858】[Scoi2010]序列操作 线段树
- bzoj 1858 序列操作(线段树)
- bzoj 2962 序列操作(线段树)
- DexException: Multiple dex files define Lcom/squareup/leakcanary/
- A + B Problem II(大数加法hd1002)
- Android-------多渠道打包
- callback机制
- [JZOJ5365]通信
- bzoj2962 序列操作 线段树
- 简单的异常处理
- hdu 4465 概率+数学处理
- 3532:最大上升子序列和(2.6基本算法之动态规划)
- Winform(XtraReport)实现打印方法(转载)
- 比特率与波特率的区别与联系
- hdu-5924-Mr. Frog’s Problem
- CVTE前端面试
- (三)几种排序算法的学习总结(快速排序)