zoukankan      html  css  js  c++  java
  • POJ 3378 (大整数加法+树状数组)

      题意:给一个长度为N(N < 50000)的序列,求这个序列中长度为5的递增子序列的个数。

    思路:对于长度为5的子序列,先考虑长度为1的子序列,第i个位置以i结尾长度为1的子序列个数为1。第i个位置以i结尾长度为2的子序列个数为i之前并且小于a[i]的长度为1的子序列的个数。同理,第i位置长度为3的子序列个数为i之前小于a[i]的长度为2的子序列的个数。。。依次往后推。

    比如原序列为:(1, 2, 4, 6, 3) 推: -> (1, 1, 1, 1, 1)1 -> (0, 1, 2, 3, 2)2 -> (0, 0, 1, 3, 1)3 -> (0, 0, 0, 1, 0)4 -> (0, 0, 0, 0, 0)5

     每次统计用树状数组就可以,中间过程和结果都有可能出现超long long的情况。所以用大整数加法。

    ps:加法最后一次进位忘了。。。wa了无数次。。。

    //#pragma comment(linker,"/STACK:327680000,327680000")
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <functional>
    #include <numeric>
    #include <sstream>
    #include <stack>
    #include <map>
    #include <queue>
    
    #define CL(arr, val)    memset(arr, val, sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   (x) < (y) ? (x) : (y)
    #define Max(x, y)   (x) < (y) ? (y) : (x)
    #define E(x)        (1 << (x))
    #define iabs(x)     (x) < 0 ? -(x) : (x)
    #define OUT(x)  printf("%I64d\n", x)
    #define Read()  freopen("data.in", "r", stdin)
    #define Write() freopen("data.out", "w", stdout);
    
    typedef long long LL;
    const double eps = 1e-8;
    const double PI = acos(-1.0);
    const int inf = ~0u>>2;
    
    using namespace std;
    
    const int N = 50010;
    const int Base = 10000;
    
    int a[N], b[N];
    
    class BigNum {
    public:
        int num[7], len;
        BigNum():len(0) {}
        BigNum(int n):len(0) {
            for( ; n > 0; n /= Base)    num[len++] = n%Base;
        }
    
        BigNum Bigvalueof(LL n) {
            len = 0;
            while(n) {
                num[len++] = n%Base;
                n /= Base;
            }
            return *this;
        }
    
        BigNum operator + (const BigNum& b) {   //++
            BigNum c;
            int i, carry = 0;
            for(i = 0; i < this->len || i < b.len || carry > 0; ++i) {
                if(i < this->len)   carry += this->num[i];
                if(i < b.len)   carry += b.num[i];
                c.num[i] = carry%Base;
                carry /= Base;
            }
            c.len = i;
            return c;
        }
    
        BigNum operator += (const BigNum& b) {  //+=
            *this = *this + b;
            return *this;
        }
    
        void Print() {
            if(len == 0)    {puts("0"); return ;}
            printf("%d", num[len - 1]);
            for(int i = len - 2; i >= 0; --i) {
                for(int j = Base/10; j > 0; j /= 10) {
                    printf("%d", num[i]/j%10);
                }
            }
            puts("");
        }
    };
    
    
    
    class TreeArray : public BigNum{
    public:
        BigNum c[N];
        int n;
        TreeArray() {}
        ~TreeArray() {}
        void init(int x) {
            n = x; CL(c, 0);
        }
    
        int lowbit(int i) {return i&(-i);}
    
        void add(int p, const BigNum& val) {
            while(p <= n) {
                c[p] += val;
                p += lowbit(p);
            }
        }
    
        BigNum sum(int p) {
            BigNum res;
            res.Bigvalueof(0);
            while(p > 0) {
                res += c[p];
                p -= lowbit(p);
            }
            return res;
        }
    };
    
    int bsearch(int b[], int m, int key) {
        int l = 0, r = m, mid;
        while(l <= r) {
            mid = (r + l) >> 1;
            if(b[mid] == key)   return mid + 1;
            else if(b[mid] < key)   l = mid + 1;
            else    r = mid - 1;
        }
        return -1;
    }
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int n, m, p, i, j;
        BigNum ans, tmp;
        TreeArray ta[6];
    
        while(~scanf("%d", &n)) {
            REP(i, n) {
                scanf("%d", a + i);
                b[i] = a[i];
            }
            sort(b, b + n);
            m = 0;
            for(i = 1; i < n; ++i) {
                if(b[m] != b[i])    b[++m] = b[i];
            }
            ++m;
            REP(i, 6)   ta[i].init(m + 5);
            for(i = 0; i < n; ++i) {
                //printf("%d ", a[i]);
                a[i] = bsearch(b, m, a[i]);
                //printf("%d\n", a[i]);
            }
            ans = ans.Bigvalueof(0);
            for(i = 0; i < n; ++i) {
                p = a[i];
                ta[1].add(p, tmp.Bigvalueof(1));
                for(j = 2; j <= 5; ++j) {
                    tmp = ta[j-1].sum(p - 1);
                    if(tmp.len) ta[j].add(p, tmp);
                    if(j == 5)  ans += tmp;
                }
            }
            ans.Print();
        }
        return 0;
    }
  • 相关阅读:
    C++中pair的用法
    DFS例题:力扣200:岛屿数量
    DFS例题:力扣695:岛屿的最大面积
    DFS深度优先遍历
    java AQS源码分析
    spring实现事务原理
    java常见并发面试题目+示例代码
    java并发锁
    ThreadPoolExecutor
    线程通信
  • 原文地址:https://www.cnblogs.com/vongang/p/2866672.html
Copyright © 2011-2022 走看看