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

来源:互联网 发布:环法自行车赛 知乎 编辑:程序博客网 时间:2024/05/22 05:14

题目链接

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 abeautiful 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 whosebeautifulness 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)。

代码如下:

#include<cstdio>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<iostream>#include<map>#include<vector>#include<algorithm>#include<set>#include<cmath>using namespace std;const int nn = 110000;const int inf = 0x3fffffff;int n;int a[nn];int c[nn*2];int f1[nn],f2[nn];int tree[11000];inline int lowbit(int x){    return x&(-x);}int getmax(int id){    int re=0;    while(id>0)    {        re=max(re,tree[id]);        id-=lowbit(id);    }    return re;}void add(int id,int val){    if(id==0)        return ;    for(int i=id;i<=10000;i+=lowbit(i))    {        tree[i]=max(tree[i],val);    }}int solve(int id){    int i;    f1[0]=0;    for(i=1;i<=10000;i++)        tree[i]=0;    int tem;    for(i=id+1;i<id+n;i++)    {        if(c[i]==10000)        {            f1[i-id]=f1[i-id-1];            continue;        }        tem=getmax(10000-c[i]+1)+c[i];        f1[i-id]=max(f1[i-id-1],tem);        add(10000-c[i]+1,tem);    }    f2[n]=0;    for(i=1;i<=10000;i++)        tree[i]=0;    for(i=id+n-1;i>=id+1;i--)    {        if(c[i]==10000)        {            f2[i-id]=f2[i-id+1];            continue;        }        tem=getmax(10000-c[i]+1)+c[i];        f2[i-id]=max(f2[i-id+1],tem);        add(10000-c[i]+1,tem);    }    int re=0;    for(i=0;i<=n-1;i++)        re=max(re,f1[i]+f2[i+1]);    return re;}int ve[20],lv;int main(){    int i;    while(scanf("%d",&n)!=EOF)    {        lv=0;        for(i=0;i<n;i++)        {            scanf("%d",&a[i]);            c[i]=a[i];            c[i+n]=a[i];            if(a[i]==10000)                ve[lv++]=i;        }        int ans=0;        for(i=0;i<lv;i++)        {            ans=max(ans,solve(ve[i]));        }        printf("%d\n",ans+10000);    }    return 0;}



0 0