scu oj 4441 Necklace(dp+树状数组)(*)

来源:互联网 发布:利率敏感性缺口 数据 编辑:程序博客网 时间:2024/05/17 11:05

题目链接

Necklace

frog has n gems arranged in a cycle, whose beautifulness are a1,a2,…,an. She would like to remove some gems to make them into a beautiful necklace without changing their relative order.

Note that a beautiful necklace can be divided into 3 consecutive parts X,y,Z, where

  1. X consists of gems with non-decreasing beautifulness,
  2. y is the only perfect gem. (A perfect gem is a gem whose beautifulness equals to 10000)
  3. Z consists of gems with non-increasing beautifulness.

Find out the maximum total beautifulness of the remaining gems.

Input

The input consists of multiple tests. For each test:

The first line contains 1 integer n (1≤n≤105). The second line contains n integers a1,a2,…,an. (0≤ai≤104, 1≤number of perfect gems≤10).

Output

For each test, write 1 integer which denotes the maximum total remaining beautifulness.

Sample Input

    6    10000 3 2 4 2 3    2    10000 10000

Sample Output

    10010    10000

题意:N个数构成一个环,现在可以删除一些数,使得这个环可以分成连续的三部分:

X部分:所有数不降

Y部分:仅含一个值为10000的数

Z部分:所有数不增

(X,Y中不含值为10000的数),值为10000的数不超过10个。

求满足条件的环中,剩余数字的和最大为多少?

题解:枚举值为10000的数。确定值为10000的数的位置后,环就断成了一条链。我们可以用动态规划求出(1,i)的数的不增序列的最大和,同理求出(i,n)的不增序列的最大和。然后枚举断点即可。在动态规划的过程中需要用到树状数组优化转移(线段树为T)。

代码如下:

[cpp] view plain copy
  1. #include<cstdio>  
  2. #include<cstdio>  
  3. #include<cmath>  
  4. #include<queue>  
  5. #include<stack>  
  6. #include<string>  
  7. #include<cstring>  
  8. #include<iostream>  
  9. #include<map>  
  10. #include<vector>  
  11. #include<algorithm>  
  12. #include<set>  
  13. #include<cmath>  
  14. using namespace std;  
  15. const int nn = 110000;  
  16. const int inf = 0x3fffffff;  
  17. int n;  
  18. int a[nn];  
  19. int c[nn*2];  
  20. int f1[nn],f2[nn];  
  21. int tree[11000];  
  22. inline int lowbit(int x)  
  23. {  
  24.     return x&(-x);  
  25. }  
  26. int getmax(int id)  
  27. {  
  28.     int re=0;  
  29.     while(id>0)  
  30.     {  
  31.         re=max(re,tree[id]);  
  32.         id-=lowbit(id);  
  33.     }  
  34.     return re;  
  35. }  
  36. void add(int id,int val)  
  37. {  
  38.     if(id==0)  
  39.         return ;  
  40.     for(int i=id;i<=10000;i+=lowbit(i))  
  41.     {  
  42.         tree[i]=max(tree[i],val);  
  43.     }  
  44. }  
  45. int solve(int id)  
  46. {  
  47.     int i;  
  48.     f1[0]=0;  
  49.     for(i=1;i<=10000;i++)  
  50.         tree[i]=0;  
  51.     int tem;  
  52.     for(i=id+1;i<id+n;i++)  
  53.     {  
  54.         if(c[i]==10000)  
  55.         {  
  56.             f1[i-id]=f1[i-id-1];  
  57.             continue;  
  58.         }  
  59.         tem=getmax(10000-c[i]+1)+c[i];  
  60.         f1[i-id]=max(f1[i-id-1],tem);  
  61.         add(10000-c[i]+1,tem);  
  62.     }  
  63.     f2[n]=0;  
  64.     for(i=1;i<=10000;i++)  
  65.         tree[i]=0;  
  66.     for(i=id+n-1;i>=id+1;i--)  
  67.     {  
  68.         if(c[i]==10000)  
  69.         {  
  70.             f2[i-id]=f2[i-id+1];  
  71.             continue;  
  72.         }  
  73.         tem=getmax(10000-c[i]+1)+c[i];  
  74.         f2[i-id]=max(f2[i-id+1],tem);  
  75.         add(10000-c[i]+1,tem);  
  76.     }  
  77.     int re=0;  
  78.     for(i=0;i<=n-1;i++)  
  79.         re=max(re,f1[i]+f2[i+1]);  
  80.     return re;  
  81. }  
  82. int ve[20],lv;  
  83. int main()  
  84. {  
  85.     int i;  
  86.     while(scanf("%d",&n)!=EOF)  
  87.     {  
  88.         lv=0;  
  89.         for(i=0;i<n;i++)  
  90.         {  
  91.             scanf("%d",&a[i]);  
  92.             c[i]=a[i];  
  93.             c[i+n]=a[i];  
  94.             if(a[i]==10000)  
  95.                 ve[lv++]=i;  
  96.         }  
  97.         int ans=0;  
  98.         for(i=0;i<lv;i++)  
  99.         {  
  100.             ans=max(ans,solve(ve[i]));  
  101.         }  
  102.         printf("%d\n",ans+10000);  
  103.     }  
  104.     return 0;  
  105. }  
原创粉丝点击