CF 314C Sereja and Subsequences(树状数组)

题目链接:http://codeforces.com/problemset/problem/314/C

题意:给定一个数列a。(1)写出a的不同的所有非下降子列;(2)定义某个子列的f值为数列中各个数的乘积。(3)求所有非下降子列的f值之和。

思路:我们用s[i]表示以数字a[i]结尾的所有非下降子列的f之和。那么a必然是接在之前小于等于a的某个数之后,设这个位置为j,那么s[i]=(s[j]+1)*a[i]。也就是,a[i]可以接在其后或者自成一个子列。那么最后的答案就是所有的s值之和。这里有一个问题,就是可能有a[i]相同的,那么这样显然就重复计算。那么我们记录某个值x前一次出现的位置j,将s[j]减去即可。至于维护这个 前i项的s用树状数组。

 


int n,s[N];


void add(int pos,int x)
{
    while(pos<N)
    {
        s[pos]=(s[pos]+x)%mod;
        pos+=pos&-pos;
    }
}


int get(int pos)
{
    int ans=0;
    while(pos)
    {
        ans=(ans+s[pos])%mod;
        pos-=pos&-pos;
    }
    return ans;
}


int pre[N],a[N];


int main()
{
    RD(n); clr(pre,-1);
    int i,x;
    FOR1(i,n)
    {
        RD(x);
        a[i]=(i64)(get(x)+1)*x%mod;
        if(pre[x]!=-1) add(x,-a[pre[x]]),a[pre[x]]=0;
        pre[x]=i;
        add(x,a[i]);
    }
    int ans=0;
    FOR1(i,n) ans=(ans+a[i])%mod;
    if(ans<0) ans+=mod;
    PR(ans);
    return 0;
}

你可能感兴趣的:(sequence)