序列操作 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表示询问 ...
随机推荐
- letter combinations of a phone number(回溯)
Given a digit string, return all possible letter combinations that the number could represent. A map ...
- .haccess 配置生效
前言:网上看到有写用.haccess会影响到网站速率之类的,这里只是讲解自己的一点配置.haccess的心得,其它的之后再讨论哈~ 1.普通配置: 网上都有的那种配置 apache/conf/ht ...
- Angular为什么选择TypeScript?
原文地址:https://vsavkin.com/writing-angular-2-in-typescript-1fa77c78d8e8 本文转自:http://www.chinacion.cn/a ...
- Java并发-任务执行
大多数的应用程序都是围绕"任务执行"来构造的:任务常常是一些抽象的并且离散的工作单元.我们把应用程序的工作分解到多个任务中,可以简化程序的组织结构,提供一种自然的事物便捷来优化错误 ...
- 利用Python进行数据分析
最近在阅读<利用Python进行数据分析>,本篇博文作为读书笔记 ,记录一下阅读书签和实践心得. 准备工作 python环境配置好了,可以参见我之前的博文<基于Python的数据分析 ...
- 如何利用Python网络爬虫抓取微信朋友圈的动态(上)
今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...
- node八-核心模块、包
学会查API,远比会几个API更重要. 核心模块意义 -如果只是在服务器运行javascript代码,并没有多大意义,因为无法实现任何功能>读写文件.访问网络 -Node的用处在于它本身还提供可 ...
- Nginx负载均衡和反向代理
1:反向代理 代理就是中介,那有反向代理就有正向代理,两者的区别是什么嘞? 正向代理隐藏真实客户端,服务端不知道实际发起请求的客户端.,proxy和client同属一个LAN,对server透明: 反 ...
- Spring Boot实战笔记(五)-- Spring高级话题(Spring Aware)
一.Spring Aware Spring 依赖注入的最大亮点就是你所有的 Bean 对 Spring容器的存在是没有意识的.即你可以将你的容器替换成其他的容器,如Google Guice,这时 Be ...
- 【转】网上看到的“12个非常有用的JavaScript技巧”
1) 使用!!将变量转换成布尔类型 有时,我们需要检查一些变量是否存在,或者它是否具有有效值,从而将它们的值视为true.对于做这样的检查,你可以使用!!(双重否定运算符),它能自动将任何类型的数据转 ...