序列操作 BZOJ2962 线段树
分析:
数据范围表示:c特别的小(c<20)
我们可以考虑nlogn*c^2的算法。
线段树维护区间信息:f[i]表示在[l,r]这段区间中选择i个数相乘的和。
因此,我们可以将区间看成一个点,在PushUp的时候用背包的方式更新父节点。(仔细观察发现这是卷积)
剩下的就是一些优化了...
附上代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;
#define N 50005
#define mod 19940417
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
int C[N][21],a[N],n,Q;
char s[10];
struct node
{
ll f[21],tag,add;
int siz;
node ()
{
memset(f,0,sizeof(f));
siz=tag=add=0;
}
node operator +(const node &b)
{
node c;
c.f[0]=1;
for(int i=1;i<=20;i++)
{
for(int j=0;j<=i;j++)
{
c.f[i]+=f[j]*b.f[i-j]%mod;
c.f[i]%=mod;
}
}
c.siz=siz+b.siz;
return c;
}
void plus(ll x)
{
add+=x;
add%=mod;
for(int i=min(siz,20);i;i--)
{
ll y=x;
for(int j=1;j<=i;j++)
{
f[i]=(f[i]+y*f[i-j]%mod*C[siz-i+j][j]%mod)%mod;
y=y*x%mod;
}
}
}
void rev()
{
tag^=1;
add=(mod-add)%mod;
for(int i=min(siz,20);i;i--)
{
if(i&1)f[i]=(mod-f[i])%mod;
}
}
}tr[N<<2];
void PushUp(int rt)
{
tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
tr[rt].f[1]=a[l];
tr[rt].f[0]=tr[rt].siz=1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void PushDown(int rt)
{
if(tr[rt].tag)
{
tr[rt<<1].rev();
tr[rt<<1|1].rev();
tr[rt].tag=0;
}
if(tr[rt].add)
{
tr[rt<<1].plus(tr[rt].add);
tr[rt<<1|1].plus(tr[rt].add);
tr[rt].add=0;
}
}
void Update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
tr[rt].plus(c);
return ;
}
PushDown(rt);
int m=(l+r)>>1;
if(m>=L)Update(L,R,c,lson);
if(m<R)Update(L,R,c,rson);
PushUp(rt);
}
void Update_rev(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
tr[rt].rev();
return ;
}
PushDown(rt);
int m=(l+r)>>1;
if(m>=L)Update_rev(L,R,lson);
if(m<R)Update_rev(L,R,rson);
PushUp(rt);
}
node query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return tr[rt];
}
PushDown(rt);
int m=(l+r)>>1;
if(m>=R)return query(L,R,lson);
if(m<L)return query(L,R,rson);
return query(L,R,lson)+query(L,R,rson);
}
int main()
{
scanf("%d%d",&n,&Q);
C[0][0]=1;
for(int i=1;i<=n;i++)
{
C[i][0]=1;
for(int j=1;j<=20;j++)
{
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,n,1);
while(Q--)
{
int x,y,z;
scanf("%s%d%d",s,&x,&y);
if(s[0]=='I')
{
scanf("%d",&z);
Update(x,y,z,1,n,1);
}else if(s[0]=='R')
{
Update_rev(x,y,1,n,1);
}else
{
scanf("%d",&z);
printf("%lld\n",(query(x,y,1,n,1).f[z]+mod)%mod);
}
}
return 0;
}
序列操作 BZOJ2962 线段树的更多相关文章
- 【BZOJ2962】序列操作(线段树)
[BZOJ2962]序列操作(线段树) 题面 BZOJ 题解 设\(s[i]\)表示区间内选择\(i\)个数的乘积的和 考虑如何向上合并? \(s[k]=\sum_{i=0}^klson.s[i]*r ...
- BZOJ_1858_[Scoi2010]序列操作_线段树
BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...
- 【BZOJ1858】序列操作(线段树)
[BZOJ1858]序列操作(线段树) 题面 BZOJ 题解 这题思路很简单,细节很烦,很码 维护区间翻转和区间赋值标记 当打到区间赋值标记时直接覆盖掉翻转标记 下放标记的时候先放赋值标记再放翻转标记 ...
- [bzoj2962]序列操作_线段树_区间卷积
序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...
- 2019.01.04 bzoj2962: 序列操作(线段树+组合数学)
传送门 线段树基础题. 题意:要求维护区间区间中选择ccc个数相乘的所有方案的和(c≤20c\le20c≤20),支持区间加,区间取负. 由于c≤20c\le20c≤20,因此可以对于每个线段树节点可 ...
- [SCOI2010]序列操作 BZOJ1858 线段树
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
- BZOJ1858 [Scoi2010]序列操作(线段树)
题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...
- bzoj1858SCOI 序列操作 (线段树)
题目大意: 给定一个长度为n的01序列为,现在有m种操作 \(0\ a\ b\) 把\([a,b]\)的数全部修改为0 \(1\ a\ b\) 把\([a,b]\)的数全部修改为1 \(2\ a\ b ...
- BZOJ_2962_序列操作_线段树
Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问 ...
随机推荐
- 面试题:JQuery有几种选择器?
很多种,大概归纳为9种. (1)基本 #id element .class * selector1,selector2,selectorN (2)层次选择器: ancestor descendant ...
- 如何写jquery插件
首页 新文章 联系 管理 订阅 自己写一个 jQuery 插件 我知道这一天终将会到来,现在,它来了. 需求 开发 SharePoint 的 CSOM 应用时,经常需要在网页上输出一 ...
- linux命令TOP参数load average详解[转]
我们知道判断一个系统的负载可以使用top,uptime等命令去查看,它分别记录了一分钟.五分钟.以及十五分钟的系统平均负载……我们知道判断一个系统的负载可以使用top,uptime等命令去查看,它分别 ...
- 阿里REDIS优化
- VS 和 VAssistX 常用快捷键
----------------------------------------------------------------函数跳转-------------------------------- ...
- 关于JavaScript的那些话
1.初学者动手环境----推荐Chrome的控制台(F12调用)2.JS中两个非常重要的数据类型是对象和数组.3.JavaScript 程序是用Unicode字符集编写的.4.JavaScript是区 ...
- ruby the diference between gets and gets.chomp()
ruby the diference between gets and gets.chomp() 二者都是可以获取用户命令行输入的函数,但是 gets获取内容后,后面 附带了 多余的换行符号'\n'; ...
- java接受安卓及ios App上传的图片,并保存到阿里OSS
做后台的时候,写了两个方法,分别用来获取安卓和苹果IOS端上传的头像,保存到阿里云OSS图片存储服务器上.(SMM框架) 安卓及H5版本: /** * 上传用户头像 */ @RequestMappin ...
- Interesting卡常数
C++ Interesting卡常数 作为一名OIer,在Noip中卡(kǎ 我就爱读kǎ)常数可以说是必备技巧.在此总结一下我所知卡常数的神奇手法: IO优化 fread 和 fwrite ,如果还 ...
- UML语言中五大视图和九种图形纵览
UML语言纵览 视图 UML语言中的视图大致分为如下5种: 1.用例视图.用例视图强调从系统的外部参与者(主要是用户)的角度看到的或需要的系统功能. 2.逻辑视图.逻辑视图从系统的静态结构和动态行为角 ...