zoukankan      html  css  js  c++  java
  • bzoj 2962 序列操作

    2962: 序列操作

    Time Limit: 50 Sec  Memory Limit: 256 MB
    [Submit][Status][Discuss]

    Description

      有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这一段区间中选择c个数相乘的所有方案的和mod 19940417的值。

    Input

      第一行两个数n,q表示序列长度和操作个数。
      第二行n个非负整数,表示序列。
      接下来q行每行输入一个操作I a b c或者 R a b或者Q a b c意义如题目描述。

    Output

      对于每个询问,输出选出c个数相乘的所有方案的和mod19940417的值。

    Sample Input

    5 5
    1 2 3 4 5
    I 2 3 1
    Q 2 4 2
    R 1 5
    I 1 3 -1
    Q 1 5 1

    Sample Output

    40
    19940397
    样例说明
      做完第一个操作序列变为1 3 4 4 5。
      第一次询问结果为3*4+3*4+4*4=40。
      做完R操作变成-1 -3 -4 -4 -5。
      做完I操作变为-2 -4 -5 -4 -5。
      第二次询问结果为-2-4-5-4-5=-20。

    HINT

      100%的数据n<=50000,q<=50000,初始序列的元素的绝对值<=109,I a b c中保证[a,b]是一个合法区间,|c|<=109,R a b保证[a,b]是个合法的区间。Q a b c中保证[a,b]是个合法的区间1<=c<=min(b-a+1,20)。

    Source

    中国国家队清华集训 2012-2013 第三天

    我写的题解看这里的T2

    http://www.cnblogs.com/TheRoadToTheGold/p/7723564.html 

    网上的参考题解

    http://blog.csdn.net/werkeytom_ftd/article/details/51767696

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 50001
    
    const int mod=19940417;
    
    typedef long long LL;
    
    int n;
    
    int C[N][21];
    
    int f[N<<2];
    int siz[N<<2],mid[N<<2];
    bool rev[N<<2];
    
    struct node { int sum[21]; }ans[N<<2];
    
    void read(int &x)
    {
        x=0; int ff=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') ff=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=ff; 
    }
    
    int tot=0;
    
    void MOD(int &a,int b)
    {
        a+=b;
        a-= a>=mod ? mod : 0;
    }
    
    void pre(int n)
    {
        C[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            C[i][0]=1;
            for(int j=1;j<=min(i,20);j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
    
    void update(int k)
    {
        for(int i=1;i<=20;i++)
        {
            ans[k].sum[i]=0;
            for(int j=1;j<i;j++) MOD(ans[k].sum[i],1ll*ans[k<<1].sum[j]*ans[k<<1|1].sum[i-j]%mod);
            MOD(ans[k].sum[i],ans[k<<1].sum[i]); MOD(ans[k].sum[i],ans[k<<1|1].sum[i]); 
        }
    }
    
    void build(int k,int l,int r)
    {
        siz[k]=r-l+1;
        if(l==r) { read(ans[k].sum[1]); MOD(ans[k].sum[1],0); return; }
        mid[k]=l+r>>1;
        build(k<<1,l,mid[k]); build(k<<1|1,mid[k]+1,r);
        update(k);
    }
    
    void insert(int k,int w)
    {
        MOD(f[k],w);
        for(int i=20;i;i--)
        {
            int x=w;
            for(int j=i-1;j;j--,x=1ll*x*w%mod)
                MOD(ans[k].sum[i],1ll*x*ans[k].sum[j]%mod*C[siz[k]-j][i-j]%mod);
            MOD(ans[k].sum[i],1ll*x*C[siz[k]][i]%mod);
        }
    }
    
    void turn(int k)
    {
        rev[k]^=1;
        if(f[k]) f[k]=mod-f[k];
        for(int i=19;i>0;i-=2) 
            if(ans[k].sum[i]) ans[k].sum[i]=mod-ans[k].sum[i];
    }
    
    void down(int k)
    {
        if(rev[k]) turn(k<<1),turn(k<<1|1),rev[k]=0;
        if(f[k]) insert(k<<1,f[k]),insert(k<<1|1,f[k]),f[k]=0;
    }
    
    void add(int k,int l,int r,int opl,int opr,int w)
    {
        if(l>=opl && r<=opr) { insert(k,w); return; }
        down(k);
        if(opl<=mid[k]) add(k<<1,l,mid[k],opl,opr,w);
        if(opr>mid[k]) add(k<<1|1,mid[k]+1,r,opl,opr,w);
        update(k);
    }
    
    void reverse(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr)  { turn(k); return; }
        down(k);
        if(opl<=mid[k]) reverse(k<<1,l,mid[k],opl,opr);
        if(opr>mid[k]) reverse(k<<1|1,mid[k]+1,r,opl,opr);
        update(k);
    }
    
    node query(int k,int l,int r,int opl,int opr,int w)
    {
        if(l>=opl && r<=opr) return ans[k];
        down(k);
        if(opr<=mid[k]) return query(k<<1,l,mid[k],opl,opr,w);
        else if(opl>mid[k]) return query(k<<1|1,mid[k]+1,r,opl,opr,w);
        else 
        {
            node L=query(k<<1,l,mid[k],opl,opr,w),R=query(k<<1|1,mid[k]+1,r,opl,opr,w);
            node tmp;
            for(int i=1;i<=w;i++)
            {
                tmp.sum[i]=(L.sum[i]+R.sum[i])%mod;
                for(int j=1;j<i;j++) MOD(tmp.sum[i],1ll*L.sum[j]*R.sum[i-j]%mod);
            }
            return tmp;
        }
    }
    
    int main()
    {
        int n,m; char c[3];
        read(n); read(m);
        pre(n);
        build(1,1,n);
        int l,r,w;
        while(m--)
        {
            scanf("%s",c); read(l); read(r);
            if(c[0]=='I')
            {
                read(w); w%=mod;
                w+= w<0 ? mod : 0;
                add(1,1,n,l,r,w);
            }
            else if(c[0]=='R') reverse(1,1,n,l,r);
            else
            {
                read(w);
                node p=query(1,1,n,l,r,w);
                printf("%d
    ",query(1,1,n,l,r,w).sum[w]);
            }
        }
    }
  • 相关阅读:
    HTML 005 标题
    HTML 004 属性
    javascript的html编码函数 (htmlSpecialChars-处理特殊字符)
    js生成二维码实例(真实有效)
    sublime快捷键
    利用jq并且添加上cookie的网页换肤
    阻止表单的默认行为
    阻止事件冒泡
    js控制图片提示(鼠标滑过显示大图片)
    jQuery.cookie插件用法自我总结
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7679195.html
Copyright © 2011-2022 走看看