• 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
    ",t[1].sum);
    85         a[x]=val;
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    java的学习笔记
    tomcat配置方法
    《编写高质量代码》学习笔记
    Servlet的学习笔记
    Http协议的学习笔记
    树莓派开箱使用分享以及一些心得
    树莓派的骚操作
    Linux的学习笔记
    msyql高级的学习笔记
    项目业务记录
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6798451.html
Copyright © 2020-2023  润新知