您的位置:首页 > 其它

HOJ 3087 Discover's Problem I

2012-03-11 22:25 344 查看

Discover's Problem I

Submitted : 31, Accepted : 14

Given a sequence , how to find the longest increasing subsequence? I think, almost all of you will think it's a piece of cake. Here comes a question about the increasing subsequence, and I think you will like it. Now you don't need to pay attention to the
length but to the sum of its elements. You should find out the increasing subsequence that the sum of its elements is max and print the sum of this increasing subsequence’s elements.

Input

The first line contains a integer T, indicating there a T cases(T<=10). Every case begin with a integer n, which is the length of the sequence. ( 1<=n<=10^5).The next line comes the elements . The values of it's elements are positive integers that no more
than 2^31-1.

Output

For every case, print the answer in a single line.

Sample Input

2
5
100 1 2 2 3
5
9 3 4 10 5


Sample output

100
19


题目大意:给你一列数共n个(1<=n<=10^5),求最大的上升和序列。

分析:树状数组+DP 或则 线段树+DP现在我们先讲一下:树状数组+DP实际上状态转移方程是很容易想出的,dp[i]=max(dp[j])+a[i](其中0<j<i)关键是如何降低复杂度来实现快速的寻找最大的前i-1项中的最大上升和子序列。现在来说明一下如何用树状数组来实现快速的查询:按数的大小从小到大的排一下序,然后再按照数字的大小插入这样就保证了已经插入的就一定比插入的小,那么单调递增就能保证了,现在还一个需要确保,就是先后问题。由于树状数组如果按照排序前的序号插入的话,那么我们只统计他们的序号前面的就同样可以保证先后问题,仔细想一想其实没那么难的。

我们来寻找一下此问题的本源思想。我们是求上升且最大的子序列和,那么问题来了上升且最大,二这两个又不是单调的关系,无论怎样我们的快速查找的方法都只是一个排序的标准即一个判断条件。因此我们就想办法了,如果先确定一个不就OK了,寻找区间最大的方法是有的,因此我们就想方法先把单调升序列确定,然后查询区间的最大值。让序列在查询的过程中保持升序列的确很难想,现在介绍一下实际具体的做法:

1.设结构体,包含两个变量:数值,下标

2.按照数值从小到大的规则排序

3.遍历排序后的序列,按照结构体中的下标插入树状数组中:求出树状数组中插入位置前的最大的递升序列和,加上当前结构体中的数值再插入

4.遍历求出最大值关键是树状数组如何操作,下面还是不理解记住吧!

代码如下

/*

* File: main.cpp

* Author: Administrator

*

* Created on 2012年3月11日, 下午6:21

*/

#include <cstdlib>

#include <cstdio>

#include <iostream>

#include <algorithm>

#include <cmath>

using namespace std;

const int MAX = 100001;

long long a[MAX];

long long dp[MAX];

/*

* 这个是DP的思想,但是要实现DP还需一定的技巧

*/

int lowbit(int x) {

return x & (-x);

}

void add(int x, long long p) {

while (x < 100001) {

a[x] = max(p, a[x]);

x += lowbit(x);

}

}

long long sum(int x) {

long long res = 0;

while (x) {

res = max(res, a[x]);

x -= lowbit(x);

}

return res;

}

struct node {

int pos;

int element;

bool operator<(const node & a)const {

if (element != a.element) {

return element < a.element;

}

return pos > a.pos;

}

} Node[MAX];

int main() {

int T;

int n;

while (scanf("%d", &T) != EOF) {

while (T--) {

scanf("%d", &n);

memset(dp, 0, sizeof (dp));

memset(a, 0, sizeof (a));

for (int i = 1; i <= n; i++) {

scanf("%d", &Node[i].element);

Node[i].pos = i;

}

sort(Node + 1, Node + n + 1);

for (int i = 1; i <= n; i++) {

dp[Node[i].pos] = sum(Node[i].pos) + (long long)(Node[i].element);

add(Node[i].pos, dp[Node[i].pos]);

}

long long res = 0;

for (int i = 1; i <= n; i++) {

res = max(dp[i], res);

}

printf("%lld\n", res);

}

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: