4597: [Shoi2016]随机序列
来源:互联网 发布:vue 源码 编辑:程序博客网 时间:2024/06/11 19:57
4597: [Shoi2016]随机序列
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 168 Solved: 115
[Submit][Status][Discuss]
Description
你的面前有N个数排成一行。分别为A1, A2, … , An。你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者
减号或者乘号。那么一共有 3^(n-1) 种可能的表达式。你对所有可能的表达式的值的和非常感兴趣。但这毕竟太
简单了,所以你还打算支持一个修改操作,可以修改某个Ai 的值。你能够编写一个程序对每个修改都输出修改完
之后所有可能表达式的和吗?注意,修改是永久的,也就是说每次修改都是在上一次修改的基础上进行, 而不是
在最初的表达式上进行。
Input
第一行包含 2 个正整数 N 和 Q,为数的个数和询问的个数。
接下来一行 n 个非负整数,依次表示a1,a2...an
在接下来 Q 行,其中第 ?? 行两个非负整数Ti 和Vi,表示要将 Ati 修改为 Vi。其中 1 ≤ Ti ≤ N。
保证对于 1 ≤ J ≤ N, 1 ≤ i≤ Q,都有 Aj,Vi ≤ 10^4。
N,Q<=100000,本题仅有三组数据
Output
输出共 Q 行,其中第 i 行表示第 i 个询问之后所有可能表达式的和,对10^9 + 7 取模。
Sample Input
5 5
9384 887 2778 6916 7794
2 8336
5 493
3 1422
1 28
4 60
9384 887 2778 6916 7794
2 8336
5 493
3 1422
1 28
4 60
Sample Output
890543652
252923708
942282590
228728040
608998099
252923708
942282590
228728040
608998099
HINT
Source
By 佚名上传
题目描述得很难很难。。不过真正需要统计的东西其实很少
对于任意一种表达式,把乘号左右两边并起来,这样整个表达式被分为k个部分
除了第一部分,后面每部分对最终答案都没有贡献
因为这样的东西出现多少次+就会有多少个带-的式子和它抵消= =
也就是说,每个表达式对ans的贡献就是从第一个数字开始,到第一个不是*前面的数字的乘积
那么,有
单点修改的话影响后面一串,利用逆元消除之前的影响,区间修改即可
那当然是线段树维护了= =
一开始居然忘记在Modify操作里打pushdown。。。惨
可是,,,这题数据好弱啊。。。。题面里不是说非负数么!!
非负数啊,0哪里有逆元?????
但是bzoj只有三组数据。。三组,而且每一组里的数字全是正的。。
如果位置k的数字为0,那么k及其之后算出的结果都是0
可以不进行修改转而打标记
询问的话只要找到左数第一个非0位,把左边的答案拿出来就好了
用配对堆易于实现
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<ext/pb_ds/priority_queue.hpp> using namespace std; const int maxn = 1E5 + 10; const int T = 4; typedef long long LL; const LL mo = 1000000007; typedef __gnu_pbds::priority_queue<int,greater<int>,__gnu_pbds::pairing_heap_tag> Heap; int n,m,A[maxn],F[maxn],mi[maxn],c[maxn*T],Mark[maxn*T]; bool zeo[maxn]; Heap Q; Heap::point_iterator id[maxn]; int Mul(const LL &x,const LL &y) {return x*y%mo;} int Add(const LL &x,const LL &y) {return (x + y)%mo;} void pushdown(int o,int l,int r) { if (Mark[o] == 1) return; c[o] = Mul(c[o],Mark[o]); if (l == r) {Mark[o] = 1; return;} Mark[o<<1] = Mul(Mark[o<<1],Mark[o]); Mark[o<<1|1] = Mul(Mark[o<<1|1],Mark[o]); Mark[o] = 1; } void Build(int o,int l,int r) { if (l == r) { c[o] = Mul(F[l],mi[l]); Mark[o] = 1; return; } int mid = (l + r) >> 1; Mark[o] = 1; Build(o<<1,l,mid); Build(o<<1|1,mid+1,r); c[o] = Add(c[o<<1],c[o<<1|1]); } void Modify(int o,int l,int r,int ml,int mr,int x) { if (ml <= l && r <= mr) { Mark[o] = Mul(Mark[o],x); pushdown(o,l,r); return; } int mid = (l + r) >> 1; pushdown(o,l,r); if (ml <= mid) Modify(o<<1,l,mid,ml,mr,x); else pushdown(o<<1,l,mid); if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,x); else pushdown(o<<1|1,mid+1,r); c[o] = Add(c[o<<1],c[o<<1|1]); } int ksm(int x,int y) { int ret = 1; for (; y; y >>= 1) { if (y&1) ret = Mul(ret,x); x = Mul(x,x); } return ret; } int Query(int o,int l,int r,int ql,int qr) { pushdown(o,l,r); if (ql <= l && r <= qr) return c[o]; int mid = (l + r) >> 1,ret = 0; if (ql <= mid) ret = Add(ret,Query(o<<1,l,mid,ql,qr)); if (qr > mid) ret = Add(ret,Query(o<<1|1,mid+1,r,ql,qr)); return ret; } int main() { #ifdef DMC freopen("DMC.txt","r",stdin); #endif cin >> n >> m; F[0] = mi[n] = 1; mi[n-1] = 2; id[n+1] = Q.push(n+1); for (int i = 1; i <= n; i++) { scanf("%d",&A[i]); if (!A[i]) id[i] = Q.push(i),A[i] = 1,zeo[i] = 1; F[i] = Mul(A[i],F[i-1]); } for (int i = n - 2; i > 0; i--) mi[i] = Mul(mi[i+1],3); Build(1,1,n); while (m--) { int pos,x; scanf("%d%d",&pos,&x); if (zeo[pos] && x) { Q.erase(id[pos]); Modify(1,1,n,pos,n,Mul(ksm(A[pos],mo-2),x)); A[pos] = x; zeo[pos] = 0; } else if (!zeo[pos] && !x) id[pos] = Q.push(pos),zeo[pos] = 1; else if (!zeo[pos] && x) { Modify(1,1,n,pos,n,Mul(ksm(A[pos],mo-2),x)); A[pos] = x; } int k = Q.top(); if (k > 1) printf("%d\n",Query(1,1,n,1,k-1)); else puts("0"); } return 0; }
0 0
- 4597: [Shoi2016]随机序列
- bzoj 4597: [Shoi2016]随机序列
- BZOJ 4597: [Shoi2016]随机序列
- BZOJ4597 [Shoi2016]随机序列
- bzoj4597 [Shoi2016]随机序列
- BZOJ4597: [Shoi2016]随机序列
- [bzoj4597/Shoi2016]随机序列
- 【bzoj4597】[Shoi2016]随机序列 线段树
- 【BZOJ4597】【Shoi2016】随机序列 线段树
- 【bzoj4597】【Shoi2016】【随机序列】【线段树】
- [bzoj4597][Shoi2016]随机序列 线段树
- [BZOJ4597][SHOI2016]随机序列(线段树)
- C#生成随机序列
- 产生随机整数序列
- Android/Java随机序列
- 平稳随机序列
- python 随机数,随机序列
- 产生一个随机序列
- 第19天 静态导入、增强for循环、枚举
- 使用jquery怎么选择有两个class的元素?
- 驱动复习(mor8)
- js拖动div或图片
- 说明符和转义字符的解释说明
- 4597: [Shoi2016]随机序列
- C# 动态调用DLL库
- 判断两个IP是否属于同一子网
- 嵌入式面试题收集
- 缓存存取图片
- System.getProperty()
- js中字符串转json
- Java中的泛型方法
- 面向对象五大原则