2962: 序列操作

Time Limit: 50 Sec  Memory Limit: 256 MB
Submit: 1145  Solved: 378
[Submit][Status][Discuss]

Description

  有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这一段区间中选择c个数相乘的所有方案的和mod 19940417的值。

Input

  第一行两个数n,q表示序列长度和操作个数。
  第二行n个非负整数,表示序列。
  接下来q行每行输入一个操作I a b c或者 R a b或者Q a b c意义如题目描述。

Output

  对于每个询问,输出选出c个数相乘的所有方案的和mod19940417的值。

Sample Input

5 5
1 2 3 4 5
I 2 3 1
Q 2 4 2
R 1 5
I 1 3 -1
Q 1 5 1

Sample Output

40
19940397
样例说明
  做完第一个操作序列变为1 3 4 4 5。
  第一次询问结果为3*4+3*4+4*4=40。
  做完R操作变成-1 -3 -4 -4 -5。
  做完I操作变为-2 -4 -5 -4 -5。
  第二次询问结果为-2-4-5-4-5=-20。

HINT

  100%的数据n<=50000,q<=50000,初始序列的元素的绝对值<=109,I a b c中保证[a,b]是一个合法区间,|c|<=109,R a b保证[a,b]是个合法的区间。Q a b c中保证[a,b]是个合法的区间1<=c<=min(b-a+1,20)。

Source

分析:线段树套路题.类似:传送门,这类题有一个特征就是需要维护的东西比较少:c <= 20,那么就可以开一个数组分别维护这些东西.
          f[i]表示当前区间选i个数相乘的和,显然一开始f[1] = a[pos].合并的时候f[i] = 左子树的f[i] + 右子树的f[i] + 左子树的f[j] * 右子树的f[k],j+k = i. 考虑两个修改操作对答案的影响.取反操作比较简单,注意到当i是奇数时f[i]才会变号.注意,取反以后一定要通过加上模数取模来变成正数.
          第一个操作有点鬼畜.纸上写几个例子,拆项后会再合并,就差不多能发现规律:,感性理解一下就是c的k次方,c要占k个位置,而另外的位置已经被f选的数给占了,只能在剩下的位置中选c,这大概就是组合数的意义.剩下的都可以通过合并同类项得到.
       一些细节需要注意,比如取反后一定要变成正数再来运算,f[0]一定要强制等于1,用类进行运算一定要先初始化,第一个操作对于f的处理要倒序处理,这些在之前附上链接的那道题中都有体现.
     总之,都是套路啦.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const ll maxn = ,mod = ;
ll n,q;
ll a[maxn],c[maxn][]; struct node
{
ll add,cover,f[],L,R;
void init()
{
add = cover = L = R = ;
memset(f,,sizeof(f));
f[] = ;
}
} e[maxn << ]; node pushup(node a,node b)
{
node c;
c.init();
c.L = a.L;
c.R = b.R;
ll len1 = c.R - c.L + ;
ll len2 = a.R - a.L + ;
ll len3 = b.R - b.L + ;
for (ll i = ; i <= min(len2,1LL * ); i++)
for (ll j = ; j <= min(len3,1LL * ); j++)
{
if (i + j > )
break;
c.f[i + j] = (c.f[i + j] + a.f[i] * b.f[j] % mod) % mod;
}
c.f[] = ; //易错点
return c;
} void fan(ll o)
{
ll len = e[o].R - e[o].L + ;
for (ll i = ; i <= min(len,1LL * ); i++)
{
if (i % == )
{
e[o].f[i] = -e[o].f[i];
e[o].f[i] = (e[o].f[i] + mod) % mod;
}
}
e[o].cover ^= ;
e[o].add = -e[o].add;
e[o].add = (e[o].add + mod) % mod; //取反后一定要变成正数
} void jia(ll o,ll v)
{
ll len = e[o].R - e[o].L + ;
for (ll i = min(len,1LL * );i >= ; i--) //一定要倒着推
{
ll k = v;
for (ll j = i - ; j >= ; j--)
{
e[o].f[i] = (e[o].f[i] + e[o].f[j] * c[len - j][i - j] % mod * k % mod) % mod;
k = k * v % mod;
}
}
e[o].add = (e[o].add + v) % mod;
} void pushdown(ll o)
{
if (e[o].cover)
{
fan(o * );
fan(o * + );
e[o].cover = ;
}
if (e[o].add)
{
jia(o * ,e[o].add);
jia(o * + ,e[o].add);
e[o].add = ;
}
} void build(ll o,ll l,ll r)
{
e[o].init();
e[o].L = l,e[o].R = r;
if (l == r)
{
e[o].f[] = a[l] % mod;
return;
}
ll mid = (l + r) >> ;
build(o * ,l,mid);
build(o * + ,mid + ,r);
e[o] = pushup(e[o * ],e[o * + ]);
} void update1(ll o,ll l,ll r,ll x,ll y,ll v)
{
if (x <= l && r <= y)
{
jia(o,v);
return;
}
pushdown(o);
ll mid = (l + r) >> ;
if (x <= mid)
update1(o * ,l,mid,x,y,v);
if (y > mid)
update1(o * + ,mid + ,r,x,y,v);
e[o] = pushup(e[o * ],e[o * + ]);
} void update2(ll o,ll l,ll r,ll x,ll y)
{
if (x <= l && r <= y)
{
fan(o);
return;
}
pushdown(o);
ll mid = (l + r) >> ;
if (x <= mid)
update2(o * ,l,mid,x,y);
if (y > mid)
update2(o * + ,mid + ,r,x,y);
e[o] = pushup(e[o * ],e[o * + ]);
} node query(ll o,ll l,ll r,ll x,ll y)
{
if (x <= l && r <= y)
return e[o];
pushdown(o);
ll mid = (l + r) >> ;
if (y <= mid)
return query(o * ,l,mid,x,y);
else if (x > mid)
return query(o * + ,mid + ,r,x,y);
else
return pushup(query(o * ,l,mid,x,mid),query(o * + ,mid + ,r,mid + ,y));
} int main()
{
scanf("%lld%lld",&n,&q);
c[][] = ;
for (ll i = ; i <= n; i++)
{
c[i][] = ;
for (ll j = ; j <= ; j++)
c[i][j] = (c[i - ][j] + c[i - ][j - ]) % mod;
}
for (ll i = ; i <= n; i++)
scanf("%lld",&a[i]);
build(,,n);
while (q--)
{
char ch[];
ll a,b,c;
scanf("%s",ch);
if (ch[] == 'I')
{
scanf("%lld%lld%lld",&a,&b,&c);
update1(,,n,a,b,c);
}
if (ch[] == 'R')
{
scanf("%lld%lld",&a,&b);
update2(,,n,a,b);
}
if (ch[] == 'Q')
{
scanf("%lld%lld%lld",&a,&b,&c);
node temp = query(,,n,a,b);
printf("%lld\n",temp.f[c] % mod);
}
} return ;
}

bzoj2962 序列操作的更多相关文章

  1. [bzoj2962]序列操作_线段树_区间卷积

    序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...

  2. bzoj2962 序列操作 题解

    题目大意: 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这 ...

  3. 2019.01.04 bzoj2962: 序列操作(线段树+组合数学)

    传送门 线段树基础题. 题意:要求维护区间区间中选择ccc个数相乘的所有方案的和(c≤20c\le20c≤20),支持区间加,区间取负. 由于c≤20c\le20c≤20,因此可以对于每个线段树节点可 ...

  4. 【BZOJ2962】序列操作(线段树)

    [BZOJ2962]序列操作(线段树) 题面 BZOJ 题解 设\(s[i]\)表示区间内选择\(i\)个数的乘积的和 考虑如何向上合并? \(s[k]=\sum_{i=0}^klson.s[i]*r ...

  5. 【BZOJ2962】序列操作 线段树

    [BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...

  6. 【BZOJ-2962】序列操作 线段树 + 区间卷积

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 678  Solved: 246[Submit][Status][Discuss] ...

  7. Python通用序列操作

    1.序列概览 1.数据结构 序列.容器 Python中最基本的数据结构是序列,其有索引(从左到右第一个索引为0,从右到左第一个索引为-1). Python包含6中内建的序列: 列表 元组 字符串 Un ...

  8. 【BZOJ-1858】序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status ...

  9. bzoj 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MB 线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊 ...

随机推荐

  1. 图 -数据结构(C语言实现)

    读数据结构与算法分析 坑!待填! 若干定义 一个图G = (V , E)由顶点集V和边集E组成,每条边就是一个点对 如果点对是有序的,那么就叫做有向图 边可能还具有第三种成分,权值 无向图种从每个顶点 ...

  2. CsvHelper文档-6类型转换

    CsvHelper文档-6类型转换 CsvHelper使用类型转换器来转换string到对象,或者对象到string: ITypeConverter 类型转换器的结构,必须实现: public int ...

  3. Ubuntu系统下在PyCharm里用virtualenv集成TensorFlow

    我的系统环境 Ubuntu 18.04 Python3.6 PyCharm 2018.3.2 community(免费版) Java 1.8 安装前准备 由于众所周知的原因,安装中需要下载大量包,尽量 ...

  4. Hyper-V虚拟机联网设置

    转自:http://www.3lian.com/edu/2012/12-22/50492.html Windows 8中内置的Hyper-V管理器可以说给许多人带来了惊喜!在Hyper-V管理器强大的 ...

  5. java 乐观锁 vs 悲观锁

    在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 悲观锁其实就是 完全同步 比如 sync ...

  6. git中的重要指令

    git命令 任何操作都需要以 git 命令为开头 本地操作: git init 初始化一个本地仓库 新建为 master主分支 git status 查看当前分支状态 git add <文件名& ...

  7. border、margin、padding三者的区别

    当你写前端的时候,肯定会遇到border,margin和padding这几个单词. 如: padding: 16px 0; margin: 0 10px; 在CSS中,他们是表示距离的东西,很多人刚开 ...

  8. OOP 2.2 构造函数

    1.概念 成员函数的一种 名字与类名相同,可以有参数,没有返回值(void也不行) 作用:对对象进行初始化,如给成员函数赋初始值 如果定义时没有构造函数,则编译器生成一个默认无参数的构造函数 默认构造 ...

  9. WebSphere Application Server诊断和调优

    近段时间,我们项目中用到的WebSphere应用服务器(WAS),但在客户的production环境下极不稳定,经常宕机.给客户造成非常不好的影响,同时,也给项目组很大压力.为此,我们花了近一个月时间 ...

  10. 浅谈 Sql Server 触发器

    一.触发器概念 1.1.触发器特征         1.1.1.触发器是在对表进行增.删.改时,自动执行的存储过程.触发器常用于强制业务规则,它是一种高级约束,通过事件进行触发而被执行.        ...