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 取模。
题解
首先想到+、-号会导致后面的所有结果相互抵消。所以对答案有贡献的是前面一直是连乘的部分。即第一个非乘号的前面部分
所以我们只需要维护前缀积,修改的时候线段树区间修改,先预处理逆元就可以做了
我认为这道题最关键的地方就是+、-号相互抵消,一下子简化了问题。一开始想是否有规律,真实太蠢了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 100020 7 8 typedef long long ll; 9 const ll mod = 1e9 + 7; 10 struct node{ 11 int ls,rs; 12 ll sum,mul; 13 }sgt[maxn * 4]; 14 ll inv[maxn],fac[maxn],sum[maxn],pow[maxn]; 15 int n,a[maxn],q,rt,tot; 16 17 inline ll power(ll x,int y){ 18 ll res = 1; 19 while ( y ){ 20 if ( y & 1 ) res = res * x % mod; 21 x = x * x % mod; 22 y >>= 1; 23 } 24 return res % mod; 25 } 26 void init(){ 27 for (int i = 1 ; i <= 10000 ; i++) inv[i] = power(i,mod - 2); 28 pow[0] = 1; 29 for (int i = 1 ; i <= 100000 ; i++) pow[i] = pow[i - 1] * 3ll % mod; 30 } 31 inline void update(int x){ 32 sgt[x].sum = sgt[sgt[x].ls].sum + sgt[sgt[x].rs].sum; 33 if ( sgt[x].sum >= mod ) sgt[x].sum -= mod; 34 } 35 void build(int &x,int l,int r){ 36 x = ++tot; 37 sgt[x].mul = 1; 38 if ( l == r ){ 39 if ( l == n ) sgt[x].sum = sum[l]; 40 else sgt[x].sum = sum[l] * pow[n - l - 1] * 2ll % mod; 41 return; 42 } 43 int mid = (l + r) >> 1; 44 build(sgt[x].ls,l,mid); 45 build(sgt[x].rs,mid + 1,r); 46 update(x); 47 } 48 inline void mul(int x,ll d){ 49 sgt[x].sum = sgt[x].sum * (ll)d % mod; 50 sgt[x].mul = sgt[x].mul * (ll)d % mod; 51 } 52 inline void pushdown(int x){ 53 if ( sgt[x].mul != 1 ){ 54 mul(sgt[x].ls,sgt[x].mul); 55 mul(sgt[x].rs,sgt[x].mul); 56 sgt[x].mul = 1; 57 } 58 } 59 void modify(int x,int l,int r,int ls,int rs,ll d){ 60 if ( ls <= l && rs >= r ){ 61 mul(x,d); 62 return; 63 } 64 pushdown(x); 65 int mid = (l + r) >> 1; 66 if ( ls <= mid ) modify(sgt[x].ls,l,mid,ls,rs,d); 67 if ( rs > mid ) modify(sgt[x].rs,mid + 1,r,ls,rs,d); 68 update(x); 69 } 70 int main(){ 71 //freopen("input.txt","r",stdin); 72 scanf("%d %d",&n,&q); 73 init(); 74 for (int i = 1 ; i <= n ; i++){ 75 scanf("%d",&a[i]); 76 } 77 sum[0] = 1; 78 for (int i = 1 ; i <= n ; i++) sum[i] = a[i] * sum[i - 1] % mod; 79 build(rt,1,n); 80 while ( q-- ){ 81 int id,v; 82 scanf("%d %d",&id,&v); 83 modify(rt,1,n,id,n,inv[a[id]]); 84 modify(rt,1,n,id,n,v); 85 a[id] = v; 86 printf("%lld\n",sgt[rt].sum); 87 } 88 return 0; 89 }
时间: 2024-10-18 19:12:19