【POJ】3378 Crazy Thairs(树状数组+dp+高精)

题目

传送门:QWQ

分析

题意:给个数列,求有多少五元上升组

考虑简化一下问题:如果题目求二元上升组怎么做。

仿照一下逆序对,用树状数组维护一下就ok了。

三元怎么做呢?

把二元的拓展一位就可以了,即把第三个也扔进树状数组

所以这题就渐渐明朗了:

用$ dp[i][x] $表示以$ A[x] $结尾的$ x $元上升组有多少个

那么:

$ dp[i][x]=\sum_{j=1}^{i-1} dp[j][x-1] (A[j]<A[i]) $

其中 $ dp[i][1]=1 $

因为多了一位大的就加了一位嘛

但这个看起来是$ O(n^2) $的,肯定要凉,所以扔进树状数组优化一下。

对了,这题还要离散化和高精度

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=50010,N = 50010, Base = 10000000;
typedef long long LL;
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("");
    }
};
typedef BigNum bign;
int n;
bign sum[maxn][8];
struct Node{
    int v,pos;
    bool operator < (const Node& a) const{ return v<a.v; }
}a[maxn];
void add(int x,int e,bign a){for(;x<=n;x+=x&-x)sum[x][e]+=a;}
bign summ(int x,int e){bign ans;for(;x>0;x-=x&-x)ans+=sum[x][e];return ans;}
int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++){scanf("%d",&a[i].v);a[i].pos=i;}
        sort(a+1,a+1+n); memset(sum,0,sizeof(sum));
        int cnt=0;
        bign ans=0;
        for(int i=1;i<=n;i++){
            add(a[i].pos,1,1);
            for(int j=2;j<=5;j++){
                add(a[i].pos,j,summ(a[i].pos-1,j-1));
            }
        }
        summ(n,5).Print();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/noblex/p/9229175.html

时间: 2024-12-25 05:38:00

【POJ】3378 Crazy Thairs(树状数组+dp+高精)的相关文章

●POJ 3378 Crazy Thairs

题链: http://poj.org/problem?id=3378 题解: 树状数组维护,高精度. 依次考虑以每个位置结尾可以造成的贡献. 假设当前位置为i,为了达到5个元素的要求,我们需要求出,在序列1-i-1中有多少个合法4元组$(a<b<c<d且A_a<A_b<A_c<A_d)$的最后那个元素是小于$A_i$的$(即为了满足a<b<c<d<i且A_a<A_b<A_c<A_d<A_i)$,求出这种四元组的个数,那么就

hdu 1541/poj 2352:Stars(树状数组,经典题)

Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4052    Accepted Submission(s): 1592 Problem Description Astronomers often examine star maps where stars are represented by points on a plan

hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 481    Accepted Submission(s): 245 Problem Description You were driving along a highway when you got caught by the road p

POJ 2892 Tunnel Warfare (树状数组+二分)

题目大意: 三个操作 D pos  将pos位置摧毁,让它和周围不相连. Q pos 问和pos 相连的有多少个村庄. R 修复最近摧毁的村庄. 思路分析: 树状数组记录这个区间有多少个1. 如果  [s-e] 有e-s+1个1 的话.那么这个区间是相连的. 这样的话,我们就可以用二分的办法求出与某个位置最大相连的数量. 还有这里二分 while(l<=r) { if(满足) { ans=mid; l=mid+1; } else r=mid-1; } #include <cstdio>

poj 2155 二维树状数组

http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17721   Accepted: 6653 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. I

poj 2309 BST 使用树状数组的lowbit

如果领悟了树状数组中的lowbit,这道题就是极其简单的,最底层都是奇数,用lowbit(x)寻找x的父亲,然后x的父亲-1就是最大数 至于lowbit是如何计算的嘛,寻找x的父亲,其实就是x+2^x的二进制末尾0的个数. #include<iostream> #include<stdio.h> using namespace std; typedef long long ll; ll lowbit(int x){ return x&(-x); } int main(){

hdu4455之树状数组+DP

Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1571    Accepted Submission(s): 459 Problem Description XXX has an array of length n. XXX wants to know that, for a given w, what is

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

POJ 3378 Crazy Thairs(树状数组+DP)

[题目链接] http://poj.org/problem?id=3378 [题目大意] 给出一个序列,求序列中长度等于5的LIS数量. [题解] 我们发现对于每个数长度为k的LIS有dp[k][i][a[i]]=dp[k-1][i-1][0~a[i]-1] 我们用5个树状数组维护不同长度的LIS,递推即可,注意答案超过LL,需要用大数. [代码] #include <cstdio> #include <algorithm> #include <cstring> usi