poj 3378 crazy thairs

题目大意:

一个数列,求i,j,k,l,m满足: 1 ≤ i < j < k < l < m ≤ N  且 Ai < Aj < Ak < Al < Am

有几组不同的i,j,k,l,m

思路:

显而易见是:四个树状数组搞定

但是看了一眼数据量:(1 ≤ N ≤ 50000) ,每个数不超过109

这就很恶心,需要高精度(还是压位!!!)和离散化

然后就是写完上述两个小技巧再加上树状数组的正经代码

PS:小技巧比正经的树状数组难写到不知道哪里去了,小技巧调了有5个多小时 TAT,果然还是太菜了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<queue>
#define ll long long
#define inf 2147483611
#define MAXN 101010
#define mod 1000000000
using namespace std;
inline ll read()
{
    ll x=0,f=1;
     char ch;ch=getchar();
     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
     return x*f;
}
struct bign
{
    ll num[100],len;
    bign()
    {
        memset(num,0,sizeof(num));
        len=0;
    }
    void clear()
    {
        memset(num,0,sizeof(num));
        len=0;
    }
    void plusn(ll b)
    {
        ll cnt=0;
        while(b) num[cnt++]+=b%mod,b/=mod;
        for (ll i=0;i<len;i++) num[i+1]+=num[i]/mod,num[i]%=mod;
        while(num[len]>=mod) num[len+1]+=num[len]/mod,num[len]%=mod,len++;
    }
    void printn()
    {
        printf("%lld",num[len]);
        for(int i=len-1;i>=0;i--)
        {
            printf("%09lld",num[i]);
        }
        printf("
");
    }
}ans;
ll n,g[MAXN];
ll c[6][MAXN];
struct ar
{
    ll val,pos;
    ar(){val=pos=0;}
}a[MAXN];
bool cmp1(ar t,ar r) {return t.val<r.val;}
ll lowbit(ll x) {return x&(-x);}
void add(ll x,ll i,ll v) {while(i<=MAXN) {c[x][i]+=v;i+=lowbit(i);}}
ll sum(ll x,ll i) 
{
    ll ans=0;
     while(i)
     {
          ans+=c[x][i];
        i-=lowbit(i);
    }
     return ans;
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    ll k;
    while((scanf("%lld",&n))!=EOF)
    {
          for(ll i=1;i<=n;i++) {a[i].val=read();a[i].pos=i;}
          sort(a+1,a+n+1,cmp1);
          ll cnt=1;
          for(ll i=1;i<=n;i++) {g[a[i].pos]=cnt;if(a[i].val!=a[i+1].val) cnt++;}
          ans.clear();
          memset(c,0,sizeof(c));
          for(ll i=1;i<=n;i++)
          {
               ll k=1;
               add(0,g[i],k);
               if(g[i]==1) continue;
               for(int j=1;j<=4;j++)
               {
                k=sum(j-1,g[i]-1);
                add(j,g[i],k);
               }
               ans.plusn(k);
        }
          ans.printn();
     }
}
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7570557.html