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\n",cas++,sum(n));
}
return 0;
}