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("\n");
    }
}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();
     }
}

时间: 2024-10-04 20:09:08

poj 3378 crazy thairs的相关文章

POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP

Crazy Thairs Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6598   Accepted: 1636 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ≤ N ≤ 50000) numbers, which  are no more than 109, Crazy Thair is a g

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

●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)$,求出这种四元组的个数,那么就

【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 $ 因为多了一位大的就

poj 1200 Crazy Search

题目: 链接:点击打开链接 题意: 输入n和nc,以及字符串s,输出长度为n的不同字串的个数. 算法: 思路: 用hash判重(hash值......),看了大牛的代码,对hash还是不甚理解.... 代码: #include<iostream> #include<cstring> #include<cstdio> #include<cstdio> using namespace std; #define MAXN 16000010 const int MA

POJ 1200 Crazy Search(Hash)

Description Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a given text. Such number could be the number of different substrings of a given size that exist in t

POJ 1200 Crazy Search (字符串hash)

题目大意: 分析长度为n的子串有多少种. 思路分析: 对于没出现的字符,将其分配一个数字. 然后将子串看做一个nc进制的数. 然后hash判断. #include <cstdio> #include <iostream> #include <algorithm> #include <map> #include <cstring> #include <string> using namespace std; bool vis[26666

Poj 1200 Crazy Search(字符串Hash)

Poj 1200 题意:给你一个n和m以及一个有m个不同字母组成的字符串,问有多少个长度为n的不同字符子串: 题解:以m为进制进行Hash.虽然是看了解题报告才会的但必须要理解并且学会运用:https://www.cnblogs.com/gj-Acit/archive/2013/05/15/3080734.html. #include<cstring>//别用set,set的添加是红黑树实现时间复杂度是O(logN),在这里会超时 #include<cstdio> #define

树状数组(BIT)

树状数组的原英文表达:Binary Indexed Tree(BIT),直译的意思便是:二进制标记树 如果数组A是基础数组,数组C是区间数组.那么,在具体介绍数组C的特点前,先给出如下的树状关系图: 仔细观察上图,容易发现: 数组C[]分别代表的区间为: C1=A1 [1,1] C2=C1+A2=A1+A2 [1,2] C3=A3 [3,3] C4=C2+C3+A4=A1+A2+A3+A4 [1,4] C5=A5 [5,5] C6=C5+A6=A5+A6 [5,6] C7=A7 [7,7] C8