bzoj2962: 序列操作

来源:互联网 发布:结婚线路图制作软件 编辑:程序博客网 时间:2024/06/06 00:37

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
题解:线段树。懒得打题解,放张图吧。
http://my.csdn.net/my/album/detail/1834139
代码无脑longlong
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define mod 19940417#define ll long longconst ll N=60100;ll n,q;struct node{    ll sum[26];}sa[N*4];ll c[N][36],aa[N];ll p1[N*4],d1[N*4];//标记相反数,加数 node update(node a,node b){    node c;    for(ll i=1;i<=20;i++) c.sum[i]=0;c.sum[0]=1;    for(ll i=1;i<=20;i++)    for(ll j=0;j<=i;j++)    (c.sum[i]+=(a.sum[j]*b.sum[i-j])%mod+mod)%=mod;    return c;}void built(ll k,ll l,ll r){    sa[k].sum[0]=1;    if(l==r){sa[k].sum[1]=aa[l];return;}    ll mid=(l+r)>>1;    built(k<<1,l,mid);built(k<<1|1,mid+1,r);    sa[k]=update(sa[k<<1],sa[k<<1|1]);}void get_mark(ll k,ll l,ll r,ll v,ll p){    ll f[30];ll len=r-l+1;    if(p)    {        for(ll i=1;i<=20;i++) if(i%2==1) sa[k].sum[i]=(mod-sa[k].sum[i])%mod;        p1[k]=!p1[k];d1[k]=(mod-d1[k])%mod;    }    if(v)    {        f[0]=1;for(ll i=1;i<=20;i++) f[i]=(f[i-1]*v+mod)%mod;        ll temp;         for(ll i=20;i>=1;i--)        {            temp=0;            for(ll j=0;j<=i;j++)            {            (temp+=((f[j]*sa[k].sum[i-j])%mod*c[len-i+j][j])%mod+mod)%=mod;             }            sa[k].sum[i]=temp;        }    }    d1[k]=(d1[k]+v+mod)%mod;}void pushdown(ll k,ll l,ll r){    ll mid=(l+r)>>1;    get_mark(k<<1,l,mid,d1[k],p1[k]);    get_mark(k<<1|1,mid+1,r,d1[k],p1[k]);    d1[k]=0;if (p1[k]) p1[k]=!p1[k];  }void insert(ll k,ll l,ll r,ll l1,ll rr,long long v,ll pp){    ll mid=(l+r)>>1;    if (l1<=l&&r<=rr){get_mark(k,l,r,v,pp);return;}    if (p1[k]||d1[k]) pushdown(k,l,r);    if (l1<=mid) insert(k<<1,l,mid,l1,rr,v,pp);    if (rr>mid) insert(k<<1|1,mid+1,r,l1,rr,v,pp);    sa[k]=update(sa[k<<1],sa[k<<1|1]);   }  node query(ll k,ll l,ll r,ll l1,ll rr){    node ans,t1,t2;ll mid=(l+r)>>1;bool f1(0),f2(0);    if (l1<=l&&r<=rr) return sa[k];    if (p1[k]||d1[k]) pushdown(k,l,r);     if (l1<=mid) t1=query(k<<1,l,mid,l1,rr),f1=1;    if (rr>mid) t2=query(k<<1|1,mid+1,r,l1,rr),f2=1;    if (!f1) return t2;if (!f2) return t1;ans=update(t1,t2);return ans;  } int main(){    scanf("%lld%lld",&n,&q);    for(ll i=1;i<=n*4;i++) sa[i].sum[0]=1;c[0][0]=1;    for(ll i=1;i<=n;i++)    {        c[i][0]=1;c[i][i]=1;        for(ll j=1;j<=20;j++)        c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;    }    for(ll i=1;i<=n;i++)    scanf("%lld",&aa[i]);built(1,1,n);    char s[6];    ll a,b,c;    for(ll i=1;i<=q;i++)    {        scanf("%s",s);        if(s[0]=='I'){scanf("%lld%lld%lld",&a,&b,&c);insert(1,1,n,a,b,c,0);}        if(s[0]=='R'){scanf("%lld%lld",&a,&b);insert(1,1,n,a,b,0,1);}        if(s[0]=='Q'){scanf("%lld%lld%lld",&a,&b,&c);node yu;yu=query(1,1,n,a,b);printf("%lld\n",(yu.sum[c]+mod)%mod);}    }  }


原创粉丝点击