序列操作 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表示询问 ...
随机推荐
- post请求参数Json字符串包含数组的校验和处理 -工作随记-备查工具
package com.xxxx.live.webapp.selvert; import java.io.BufferedReader; import java.io.IOException; imp ...
- Collections.sort自定义排序的使用方法
Collections.sort自定义排序的使用方法 总结:Collections可以对List进行排序:如果想对Map进行排序,可以将Map转化成List,进行排序: public static v ...
- 用Socket编写的聊天小程序
Socket是什么? 是套接字,除此之外我也不太清楚,先略过 直接上实例,首先服务端: ; //自定义端口号 private string ServerUser = "Tracy" ...
- Ubuntu 14.10下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具)
Ubuntu 14.10下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具) 最近因为项目关系,收朋友之托,想制作秀场网站,但是因为之前一直没有涉及到这 ...
- Django升级1.8的一些问题
1.最明显的问题当然是Settings设置中关于模板的设置数据结构发生变化,这个就不细说了,你开个Django的1.8的新项目就知道怎么改了 2.migrations问题,这个问题是1.8最主要的修改 ...
- Linux/Windows 文件交互读取转义字符变换
- 神奇的namespace使用
一大波概念正在来袭: 作用域与命名空间 相关概念 与命名空间相关的概念有: 声明域(declaration region)—— 声明标识符的区域.如在函数外面声明的全局变量,它的声明域为 ...
- threesum
算法题 问题描述:在一些给定的数中,找到三个数,他们相加的和是0,并且这三个数的组合是不能重复的 例子: input [-1, 0, -1, 2, 1] Output [[-1, 1 ,0], [-1 ...
- DevOps之五 Tomcat的安装与配置
安装说明 安装环境:CentOS-7 安装方式:源码安装 软件:apache-tomcat-9 下载地址:https://tomcat.apache.org/download-90.cgi 一.安装t ...
- 双网卡+mitmproxy+iptables搭建SSL中间人(支持非HTTPS协议)
"想要解决一个问题,最根本方法的就是了解这一切是如何工作的,而不是玄学." --ASCII0X03 最近学习发现现在很多现成的安卓SSL中间人工具和教程都只针对HTTPS流量,比如 ...