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 }

 

posted @ 2017-05-02 21:06  ws_ccd  阅读(209)  评论(0编辑  收藏  举报