【BZOJ4597】[Shoi2016]随机序列

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

Sample Output

890543652
252923708
942282590
228728040
608998099

题解:+号和-号就是逗你玩的,因为如果把+换成-,那么对应位置的值就会变成相反数,最后都会抵消,所以只有一开始的连续的一段乘号是有用的。

所以用s[i]表示前缀乘积,答案可以表示成$\sum\limits_{i=1}^{n-1}s[i]*3^{n-i-1}*2+s[n]$(注意最后一个不*2),用线段树维护一下即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const ll P=1000000007;
const int maxn=100010;
int n,m;
ll A[maxn],v[maxn],s[maxn<<2],ts[maxn<<2];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
inline ll pm(ll x,ll y)
{
ll z=1;
while(y)
{
if(y&1) z=z*x%P;
x=x*x%P,y>>=1;
}
return z;
}
void build(int l,int r,int x)
{
if(l==r)
{
s[x]=v[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,lson),build(mid+1,r,rson);
ts[x]=1,s[x]=(s[lson]+s[rson])%P;
}
void updata(int l,int r,int x,int a,int b,ll c)
{
if(a<=l&&r<=b)
{
s[x]=s[x]*c%P,ts[x]=ts[x]*c%P;
return ;
}
if(ts[x]!=1)
{
s[lson]=s[lson]*ts[x]%P,s[rson]=s[rson]*ts[x]%P,ts[lson]=ts[lson]*ts[x]%P,ts[rson]=ts[rson]*ts[x]%P;
ts[x]=1;
}
int mid=(l+r)>>1;
if(a<=mid) updata(l,mid,lson,a,b,c);
if(b>mid) updata(mid+1,r,rson,a,b,c);
s[x]=(s[lson]+s[rson])%P;
}
int main()
{
n=rd(),m=rd();
int i,a,b;
ll tmp=1;
for(i=1;i<=n;i++) A[i]=v[i]=rd();
for(i=2;i<=n;i++) v[i]=v[i]*v[i-1]%P;
for(i=n-1;i>=1;i--) v[i]=(v[i]*tmp<<1)%P,tmp=tmp*3%P;
build(1,n,1);
for(i=1;i<=m;i++)
{
a=rd(),b=rd();
updata(1,n,1,a,n,b*pm(A[a],P-2)%P),A[a]=b;
printf("%lld\n",s[1]);
}
return 0;
}//5 5 9384 887 2778 6916 7794 2 8336 5 493 3 1422 1 28 4 60

【BZOJ4597】[Shoi2016]随机序列 线段树的更多相关文章

  1. BZOJ 4597: [Shoi2016]随机序列 线段树 + 思维

    Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者 减号或者乘号.那么一共有 3^(n-1) 种可能的表 ...

  2. BZOJ4597: [Shoi2016]随机序列

    Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者 减号或者乘号.那么一共有 3^(n-1) 种可能的表 ...

  3. BZOJ4597 SHOI2016随机序列(线段树)

    先考虑题目所说的太简单了的问题.注意到只要把加减号相取反,就可以得到一对除了第一项都互相抵消的式子.于是得到答案即为Σf(i)g(i),其中f(i)为前缀积,g(i)为第i个数前面所有符号均填乘号,第 ...

  4. 随机序列[SHOI2016](找规律+线段树)

    传送门 这道题的题意就是给你n个数让你在每个数之间插入+.-.*三种运算符中的一种,然后算出一个答案,再把答案加起来. 这题肯定是不能暴力的(题目都告诉你了由3n-1种结果).我们先从小的情况枚举找一 ...

  5. BZOJ4597:[SHOI2016]随机序列——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4597 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 ...

  6. 【bzoj4597】 [Shoi2016]随机序列

    可以发现加减号之间可以互相抵消. 真正加到答案里的只有一些前缀积. 记s[i]为a[1]*a[2]*a[3]...*a[i].那s[i]在答案中出现的次数就是2*3^(n-i-1); 修改一个数只会对 ...

  7. P4340 [SHOI2016]随机序列

    题目 P4340 [SHOI2016]随机序列 思维好题 做法 是否觉得水在于你是否发现加减是会抵消的,所以我们只用考虑乘的部分 一块乘只能前面无号(也就是前缀形式)才统计,所以用线段树维护区间前缀乘 ...

  8. BZOJ 4597: [Shoi2016]随机序列

    4597: [Shoi2016]随机序列 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 174[Submit][Status ...

  9. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

随机推荐

  1. 为何 IntelliJ IDEA 比 Eclipse 更好

    http://www.oschina.net/news/26929/why-intellij-is-better-than-eclipse圣战 有一些没有唯一正确答案的“永恒”的问题,例如哪个更好:是 ...

  2. 点滴积累【other】---存储过程删除所有表中的数据(sql)

    USE [QG_Mis24] GO /****** Object: StoredProcedure [dbo].[p_set1] Script Date: 07/18/2013 13:25:57 ** ...

  3. 点滴积累【JS】---JS小功能(操作Table--动态添加删除表格及数据)

    效果: 代码: <head runat="server"> <title></title> <style type="text/ ...

  4. vim跳出括号的方法

    https://github.com/Raimondi/delimitMate delimitMate是一个自动括号补全的好插件,但是,如果没有一个好的跳出括号办法,好想由打了折扣. 我目前找到最适合 ...

  5. python访问纯真IP数据库的代码

    通过IP地址判断客户端是网通的还是电信的. 使用一个纯文本的IP纯真数据库,用Python写了一个小程序. 核心代码: #!/usr/bin/env python #site www.jbxue.co ...

  6. Excel累加上一行的数值

    默认一拖是每一行+1,现在想加任意: =A1+X 然后一拖就可以加X了.

  7. 多线程-CountDownLatch,CyclicBarrier,Semaphore,Exchanger,Phaser

    CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数初始化CountDownLatch.调用countDown()计数减一, ...

  8. Atitit.antlr实现词法分析

    Atitit.antlr实现词法分析 1.1.  antlrworks-1.4.3.jar   wizard1 1.2. 词法的类型 id,int,float ,comment,str,char,wh ...

  9. [转]手工释放linux内存——/proc/sys/vm/drop_caches

    另一篇:http://www.linuxfly.org/post/320/   1.清理前内存使用情况 free -m 2.开始清理  echo 1 > /proc/sys/vm/drop_ca ...

  10. 【Objective-C】02-Objective-C学习及iOS开发的准备

    前言 由于大部分朋友对iOS开发还是有比较多的疑问,比如是不是一定要买iPhone和苹果笔记本才能做iOS开发?因此,这讲就为广大有意学习iOS开发的朋友们进行解惑. 一.什么是iOS开发 iOS是由 ...