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
- X consists of gems with non-decreasing beautifulness,
- y is the only perfect gem. (A perfect gem is a gem whose beautifulness equals to 10000)
- 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;
}