BZOJ4597 [Shoi2016]随机序列

Time Limit: 20 Sec  Memory Limit: 256 MB

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


sum[i]=a[1]*a[2]*……*a[i]

sum[i]对答案的贡献,总共要计算2*3^(n-i-1)次(sum[i]后面的符号不能是×,剩下的符号随便选)。sum[n]只计算一次。

线段树维护即可。

???+///与///+???可以抵消


/**************************************************************

    Problem: 4597

    User: ictsing

    Language: C++

    Result: Accepted

    Time:324 ms

    Memory:9104 kb

****************************************************************/

 

#include <iostream>

#include <cstdio>

using namespace std;

typedef long long ll;

const ll mt = 100000+5;

const ll mod = 1e9+7;

ll sum[mt<<2],val[mt],ji[mt<<2];

ll k[mt];

inline ll read()

{

    ll num=0,flag=1;

    char ch;

    do{

        ch=getchar();

        if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

        num=num*10+ch-'0';

        ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

void pushup(ll x)

{

    if(x)

    {

        ji[x]=ji[x<<1]*ji[x<<1|1]%mod;

        sum[x]=(sum[x<<1]*1ll+sum[x<<1|1]*ji[x<<1])%mod;

    }

}

void build(ll rt,ll l,ll r)

{

    if(l==r)

    {

        ji[rt]=val[l];

        sum[rt]=ji[rt]*1ll*k[l]%mod;

        return ;

    }

    ll mid=(l+r)>>1;

    build(rt<<1,l,mid);

    build(rt<<1|1,mid+1,r);

    pushup(rt);

}

void update(ll rt,ll l,ll r,ll x,ll p)

{

    if(l==r)

    {

        ji[rt]=p;

        sum[rt]=ji[rt]*1ll*k[l]%mod;

        return ;

    }

    ll mid=(l+r)>>1;

    if(x<=mid) update(rt<<1,l,mid,x,p);

    else update(rt<<1|1,mid+1,r,x,p);

    pushup(rt);

}

int main()

{

    ll n=read(),q=read();

    for(ll i=1;i<=n;i++) val[i]=read();

    k[n]=1,k[n-1]=2;

    for(ll i=n-2;i>=1;i--) k[i]=1ll*3*k[i+1]%mod;

    build(1,1,n);

    while(q--)

    {

        ll p=read(),x=read();

        update(1,1,n,p,x);

        printf("%lld\n",sum[1]%mod);

    }

    return 0;

}

 

评论

热度(6)