zoukankan      html  css  js  c++  java
  • POJ 3378 Crazy Thairs dp+树状数组

    题目:http://poj.org/problem?id=3378

    题意:求满足下列要求的5元组的个数

    1. 1 ≤ i < j < k < l < m  N
    2. Ai < Aj < Ak < Al < Am

    学习了一种机智的做法,在范围超longlong不大的时候可以使用2个longlong来避免写高精度

    首先我们对数据进行离散化

    设dp[i][j]为以 a[j] 结尾的上升 i 序列 1<=i<=5

    dp[i][j]=sum{dp[i-1][k]}  a[k]<a[j] 1<=k<j

    然后我们可以用树状数组来维护sum

    add(i,a[j],sum(i-1,a[j]-1))

    因为最后一维是答案且不需要查询,而且只有这一维的大小会爆longlong,所以我们可以用2个longlong来存放答案

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    typedef long long ll;
    const int N=5e4+5;
    const ll base=1e15;
    struct p
    {
        int x,y;
        bool operator <(const p &t) const
        {
            return x<t.x;
        }
    };
    p tem[N];
    int a[N];
    ll s[5][N],ans1,ans2;
    void add(int k,int i,ll x)
    {
        while(i<N)
        {
            s[k][i]+=x;
            i+=i&-i;
        }
    }
    ll sum(int k,int i)
    {
        ll t=0;
        while(i>0)
        {
            t+=s[k][i];
            i-=i&-i;
        }
        return t;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&tem[i].x);
                tem[i].y=i;
            }
            sort(tem+1,tem+1+n);
            memset(s,0,sizeof(s));
            a[tem[1].y]=1;
            int cnt=1;
            for(int i=2;i<=n;i++)
                if (tem[i].x==tem[i-1].x) a[tem[i].y]=cnt;
                else a[tem[i].y]=++cnt;
            ans1=ans2=0;
            for(int i=1;i<=n;i++)
            {
                add(1,a[i],1);
                for(int j=2;j<=4;j++)
                    add(j,a[i],sum(j-1,a[i]-1));
                ans1+=sum(4,a[i]-1);
                ans2+=ans1/base;
                ans1%=base;
            }
            if (ans2) printf("%lld",ans2);
            printf("%lld
    ",ans1);
        }
        return 0;
    }
    

      

  • 相关阅读:
    [转]
    Linux
    [转]
    [转]
    Linux 高级网络编程
    [转]
    [译]- 6-1 排列窗体上的控件(Laying Out Widgets on a Form)
    [转]
    [转]
    the thread has exited with code -1073741819
  • 原文地址:https://www.cnblogs.com/bk-201/p/7453714.html
Copyright © 2011-2022 走看看