POJ 3378 树状数组+DP+离散化+高精度

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

 

这题的dp的方法挺经典的,方程大家应该都会写(那个N^2的),我就不再赘述,这里巧妙地运用了树状数组求和

c[i][j]表示当前状态时,以j(j是数字,不是下标)为结尾的长度为i的序列个数

 

剩下的就是考验高精度了~1100+ms

 

View Code
  1 #include <cstdio>

  2 #include <cstring>

  3 #include <cstdlib>

  4 #include <iostream>

  5 #include <algorithm>

  6 

  7 #define SIZE 10

  8 

  9 using namespace std;

 10 

 11 struct BIGN 

 12 {

 13     int a[SIZE];

 14 };

 15 

 16 inline BIGN operator +(BIGN a,BIGN b)

 17 {

 18     BIGN c;

 19     memset(&c,0,sizeof c);

 20     c.a[0]=max(b.a[0],a.a[0]);

 21     int jin=0;

 22     for(int i=1;i<=c.a[0];i++)

 23     {

 24         jin+=a.a[i]+b.a[i];

 25         c.a[i]=jin%10000;

 26         jin/=10000;

 27     }

 28     if(jin) c.a[++c.a[0]]=jin;

 29     return c;

 30 }

 31 

 32 inline void give(char s[],BIGN &a)

 33 {

 34     memset(&a,0,sizeof a);

 35     int len=strlen(s);

 36     int p[4]={1,10,100,1000};

 37     for(int i=len-1,j=0;i>=0;i--,j=(j+1)&3)

 38     {

 39         if(!j) a.a[0]++;

 40         a.a[a.a[0]]=a.a[a.a[0]]+(s[i]-'0')*p[j];

 41     }

 42 }

 43 

 44 inline void prt(BIGN a)

 45 {

 46     printf("%d",a.a[a.a[0]]);

 47     for(int i=a.a[0]-1;i>=1;i--) printf("%04d",a.a[i]);

 48     puts("");

 49 }

 50 

 51 BIGN c[6][50010],ans;

 52 int n,bh;

 53 

 54 struct BZ

 55 {

 56     int x,h,id;

 57 }bz[50010];

 58 

 59 void read()

 60 {

 61     for(int i=1;i<=n;i++)

 62     {

 63         scanf("%d",&bz[i].x);

 64         bz[i].id=i;

 65     }    

 66 }

 67 

 68 inline bool cmp_x(const BZ &a,const BZ &b)

 69 {

 70     return a.x<b.x;

 71 }

 72 

 73 inline bool cmp_id(const BZ &a,const BZ &b)

 74 {

 75     return a.id<b.id;

 76 }

 77 

 78 inline int lowbit(int x)

 79 {

 80     return x&-x;

 81 }

 82 

 83 void lsh()

 84 {

 85     sort(bz+1,bz+1+n,cmp_x);

 86     bz[1].h=2; bh=2;

 87     for(int i=2;i<=n;i++)

 88     {

 89         if(bz[i].x!=bz[i-1].x) bz[i].h=++bh;

 90         else bz[i].h=bh;

 91     }

 92     sort(bz+1,bz+1+n,cmp_id);

 93 }

 94 

 95 inline BIGN getsum(int p,int num)

 96 {

 97     BIGN rt;

 98     give("0",rt);

 99     while(num)

100     {

101         rt=rt+c[p][num];

102         num-=lowbit(num);

103     }

104     return rt;

105 } 

106 

107 inline void updata(int p,int q,BIGN sy)

108 {

109     while(q<=bh)

110     {

111         c[p][q]=c[p][q]+sy;

112         q+=lowbit(q);

113     }

114 }

115 

116 void go()

117 {

118     BIGN one,tmp; give("1",one); give("0",ans);

119     for(int i=0;i<=bh;i++)

120         for(int j=1;j<=5;j++)

121             give("0",c[j][i]);

122     for(int i=1;i<=n;i++) 

123     {

124         updata(1,bz[i].h,one);

125         for(int j=2;j<=5;j++)

126         {

127             tmp=getsum(j-1,bz[i].h-1);

128             updata(j,bz[i].h,tmp);

129         }

130     }

131     ans=getsum(5,bh);

132     prt(ans);

133 }

134 

135 int main()

136 {

137     while(scanf("%d",&n)!=EOF)

138     {

139         read();

140         lsh();

141         go();

142     }

143     return 0;

144 }

 

发现数组开大了,一直tle,搞了半天才AC。。。

你可能感兴趣的:(树状数组)