lightoj 1085【离散化+树状数组】

题意:
计算一个序列里有多少个上升子序列
思路:
先离散化一下,按照值排序,如果相同的就按照坐标从大到小排序,这样就可以避免重复计算。
树状数组存的是以a[i]结尾的子序列之和;
dp[a[i]]=sigma(a[i]-1)+1;
OK,还是很简单的;

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
const LL mod=1000000007;
LL dp[N];
struct asd{
    LL val;
    int id;
};
asd q[N];
int n;
bool cmp(asd x,asd y)
{
    if(x.val<y.val)
        return 1;
    if(x.val==y.val)
        return x.id>y.id;
    return 0;
}

int lowbit(int x)
{
    return x&(-x);
}

void add(int x,LL val)
{
    val%=mod;
    while(x<=n+7)
    {
        dp[x]=(dp[x]+val)%mod;
        x+=lowbit(x);
    }
}

LL sum(int x)
{
    LL ans=0;
    while(x>0)
    {
        ans=(ans+dp[x])%mod;
        x-=lowbit(x);
    }
    return ans;
}

int main()
{
    int T;
    int cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&q[i].val);
            q[i].id=i;
        }
        sort(q+1,q+n+1,cmp);

        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            add(q[i].id,sum(q[i].id-1)+1);
        }
        printf("Case %d: %lld
",cas++,sum(n));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934789.html