bzoj 4597: [Shoi2016]随机序列
说实话,大大的良心题2333,我这个蒟蒻都会做2333(这是今天做出来第一个pj+难度的题2333)(太弱了)
(3^(n-1)暴力肯定是不对的2333)
现在可以发现一个奇妙的性质,就是对于一个位置,前面的全是乘号的话,那么这个位置填加和减号,那么后面产生的贡献就正好正负抵消了。而这个位置填加减号的贡献就是3^m*2*pre_sum (pre_sum指这个位置之前的数的积,m指后面还有m个位置)
如果这个位置填乘号的话,只对后面填的情况有贡献。
这样的话,对于每个位置,都有一个值(注意最后还要加上一个所有数的乘积)
这样修改的话,就是对x位置及以后的把原数除掉,乘上新数就好了。直接上弱智版的线段树就行。
1 #include <bits/stdc++.h> 2 #define LL long long 3 #define inf 1e60 4 using namespace std; 5 inline int ra() 6 { 7 int x=0,f=1; char ch=getchar(); 8 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 9 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 10 return x*f; 11 } 12 13 const int maxn=100005; 14 const int mod=1e9+7; 15 16 int ksm(int x, int p) 17 { 18 int sum=1; 19 for (;p;p>>=1,x=(LL)x*x%mod) 20 if (p&1) sum=(LL)sum*x%mod; 21 return sum; 22 } 23 24 int inv[maxn],orz[maxn]; 25 int n,T,a[maxn]; 26 void pre() 27 { 28 inv[1]=1; 29 for (int i=1; i<=n; i++) orz[i]=1; 30 for (int i=2; i<=10000; i++) inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod; 31 } 32 33 struct seg{ 34 int l,r,mul,sum; 35 }t[maxn<<4]; 36 void update(int k) {t[k].sum=(t[k<<1].sum+t[k<<1|1].sum)%mod;} 37 void build(int k, int l, int r) 38 { 39 t[k].l=l; t[k].r=r; t[k].mul=1; 40 if (l==r) 41 { 42 t[k].sum=orz[l]; return; 43 } 44 int mid=l+r>>1; 45 build(k<<1,l,mid); build(k<<1|1,mid+1,r); 46 update(k); 47 } 48 void pushdown(int k) 49 { 50 int tmp=t[k].mul; t[k].mul=1; 51 t[k<<1].mul=(LL)t[k<<1].mul*tmp%mod; 52 t[k<<1].sum=(LL)t[k<<1].sum*tmp%mod; 53 t[k<<1|1].mul=(LL)t[k<<1|1].mul*tmp%mod; 54 t[k<<1|1].sum=(LL)t[k<<1|1].sum*tmp%mod; 55 } 56 void change(int k, int x, int y, int val) 57 { 58 int l=t[k].l,r=t[k].r; 59 if (l==x && y==r) 60 { 61 t[k].sum=(LL)t[k].sum*val%mod; 62 t[k].mul=(LL)t[k].mul*val%mod; 63 return; 64 } 65 int mid=l+r>>1; 66 if (t[k].mul!=1) pushdown(k); 67 if (y<=mid) change(k<<1,x,y,val); 68 else if (x>mid) change(k<<1|1,x,y,val); 69 else change(k<<1,x,mid,val),change(k<<1|1,mid+1,y,val); 70 update(k); 71 } 72 73 int main() 74 { 75 n=ra(); T=ra(); pre(); 76 for (int i=1; i<=n; i++) a[i]=ra(),orz[n]=(LL)orz[n]*a[i]%mod; 77 orz[1]=(LL)a[1]*ksm(3,n-2)*2%mod; 78 for (int i=2; i<n; i++) orz[i]=(LL)orz[i-1]*inv[3]%mod*a[i]%mod; 79 build(1,1,n); 80 while (T--) 81 { 82 int x=ra(),val=ra(); 83 change(1,x,n,(LL)val*inv[a[x]]%mod); 84 printf("%d\n",t[1].sum); 85 a[x]=val; 86 } 87 return 0; 88 }