• 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。。。

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    20155334 2016-2017-2 《Java程序设计》第四周学习总结
    20155334 2016-2017-2 《Java程序设计》第三周学习总结
    20155334 2016-2017-2 《Java程序设计》第二周学习总结
    20155334 2016-2017-2 《Java程序设计》第一周学习总结
    虚拟机与Linux的初体验
    20155334的第二次随笔
    使用Maven工程
    观察者模式(observer)
    GreenPlum之进程会话管理篇
    Linux下crontab命令添加Kettle作业定时任务
  • 原文地址:https://www.cnblogs.com/proverbs/p/2710551.html
Copyright © 2020-2023  润新知