SCU - 4441 Necklace(树状数组求最长上升子数列)

Necklace

frog has \(n\) gems arranged in a cycle, whose beautifulness are \(a_1, a_2, \dots, a_n\). 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 \leq n \leq 10^5\)). The second line contains \(n\) integers \(a_1, a_2, \dots, a_n\). (\(0 \leq a_i \leq 10^4\), \(1 \leq \textrm{number of perfect gems} \leq 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
#include <bits/stdc++.h>
#define  met(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int N = 1e5+50;
int C[N];
int dp1[N],dp2[N],b[N],a[2*N];
int n,m,k;
int low_bit(int x)
{
    return x&(-x);
}
void updata(int pos,int val)
{
    for(int i=pos;i<=10000;i+=low_bit(i))
        C[i]=max(C[i],val);
}
int get_max(int pos)
{
    int ans=0;
    for(int i=pos;i>0;i-=low_bit(i))
        ans=max(ans,C[i]);
    return ans;
}

int solve(int id)
{
    met(C,0);
    int cnt=0;
    for(int i=id+1;i<id+n;i++)
    {
        if(a[i]!=10000)
            b[cnt++]=a[i];
    }
    dp1[0]=b[0];
    updata(10000-b[0],b[0]);
    for(int i=1;i<cnt;i++)
    {
        dp1[i]=get_max(10000-b[i])+b[i];
        updata(10000-b[i],dp1[i]);
    }
    met(C,0);
    dp2[cnt-1]=b[cnt-1];
    updata(10000-b[cnt-1],b[cnt-1]);
    for(int i=cnt-2;i>=0;i--)
    {
        dp2[i]=get_max(10000-b[i])+b[i];
        updata(10000-b[i],dp2[i]);
    }
    int ans=0;
    for(int i=1;i<cnt;i++)
        dp1[i]=max(dp1[i],dp1[i-1]);
    for(int i=cnt-2;i>0;i--)
        dp2[i]=max(dp2[i],dp2[i+1]);
    dp2[cnt]=0;
    for(int i=0;i<cnt;i++)
        ans=max(ans,dp1[i]+dp2[i+1]);
    ans=max(ans,dp2[0]);
    return ans+10000;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            a[i+n]=a[i];
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            if(a[i]==10000)
            {
                ans=max(ans,solve(i));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
 
时间: 2024-08-01 22:45:44

SCU - 4441 Necklace(树状数组求最长上升子数列)的相关文章

ZOJ-2386 Ultra-QuickSort 【树状数组求逆序数+离散化】

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input seque

POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted: 2875 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

树状数组求逆序对

给定n个数,要求这些数构成的逆序对的个数.除了用归并排序来求逆序对个数,还可以使用树状数组来求解.树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0.从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了.把所有的加起来就是总的逆序对数.题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000.如果采用上面的思想,必然会导致空间的巨大浪费,而且由

树状数组求区间最值

树状数组求区间最值 树状数组(Binary Index Tree)利用二进制的一些性质巧妙的划分区间,是一种编程,时间和空间上都十分理想的求区间和的算法,同样我们可以利用树状数组优美的区间划分方法来求一个序列的最值 约定以 num[]  表示原数组, 以 idx[] 表示索引数组, Lowbit(x)=x&(-x) 树状数组求和时通过构造数组 idx[] 使 idx[k]=sum(num[tk]), tk [k-Lowbit(k)+1,k], 使用同样的方法构造最值索引数组: 以最大值为例, 先

HDU 5249 离线树状数组求第k大+离散化

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1160    Accepted Submission(s): 488 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的

树状数组求逆序数

poj 2299 树状数组求逆序数题目链接:http://poj.org/problem?id=2299 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <

HDU 1394 Minimum Inversion Number (树状数组求逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13942    Accepted Submission(s): 8514 Problem Description The inversion number of a given number sequence a1, a2, ..., a

hdu5792 World is Exploding(多校第五场)树状数组求逆序对 离散化

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5792 题目描述:给你n个值,每个值用A[i]表示,然后问你能否找到多少组(a,b,c,d)四个编号,四个编号互不相同,然后a < b, c < d,a代表的值小于b代表的值,c代表的值大于d代表的值. 解题思路:先考虑a和b这两个编号,遍历每一个编号作为b,然后找到b前面有多少个小于b的值,就是对于这一个编号b合理的编号a,对于每一组a和b,就可以考虑c和d,能够满足条件c和d的很显然就是除去a和

hdu 5147 Sequence II (树状数组 求逆序数)

题目链接 Sequence II Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 331    Accepted Submission(s): 151 Problem Description Long long ago, there is a sequence A with length n. All numbers in this se