hdu 1087 最大上升子序列的和(dp或线段树)

Super Jumping! Jumping! Jumping!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 23328    Accepted Submission(s): 10266

Problem Description

Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now.

The game can be played by two or more than two players. It consists of a chessboard(棋盘)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path.
Your task is to output the maximum value according to the given chessmen list.

Input

Input contains multiple test cases. Each test case is described in a line as follow:
N value_1 value_2 …value_N 
It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int.
A test case starting with 0 terminates the input and this test case is not to be processed.

Output

For each case, print the maximum according to rules, and one line one case.

Sample Input

3 1 3 2

4 1 2 3 4

4 3 3 2 1

0

Sample Output

4

10

3

 1 /*
 2 时间复杂度O(n^2)
 3 */
 4 #include <iostream>
 5 #include <cstdio>
 6 #include <cstring>
 7 using namespace std;
 8
 9 typedef __int64 LL;
10 const int maxn=1005;
11 LL dp[maxn],f[maxn];
12 inline int max(int a,int b){return a>b?a:b;}
13 int main()
14 {
15     int n,i,j;
16     while(scanf("%d",&n),n)
17     {
18         for(i=1;i<=n;i++)
19         {
20             scanf("%d",f+i);dp[i]=f[i];
21         }
22         for(i=1;i<=n;i++)
23         {
24             for(j=i-1;j>0;j--)
25                 if(f[i]>f[j])
26                     dp[i]=max(dp[i],dp[j]+f[i]);
27         }
28         LL ans=0;
29         for(i=1;i<=n;i++)
30             ans=max(ans,dp[i]);
31         printf("%I64d\n",ans);
32     }
33     return 0;
34 }
  1 /*
  2 时间复杂度O(nlogn)
  3 */
  4 #include <iostream>
  5 #include <cstdio>
  6 #include <cstring>
  7 using namespace std;
  8
  9 const int maxn = 1005;
 10 #define lson l,mid,rt<<1
 11 #define rson mid+1,r,rt<<1|1
 12 int sum[maxn<<2];
 13 int a[maxn],b[maxn],c[maxn];
 14 inline int max(int a,int b){return a> b?a:b;}
 15
 16 void swap(int &a,int &b){int t=a;a=b;b=t;}
 17
 18 void qsort(int l,int r)
 19 {
 20     if(l<r)
 21     {
 22         int t=b[l],i=l,j=r;
 23         while(i!=j)
 24         {
 25             while(b[j]>=t && i<j) j--;
 26             while(b[i]<=t && i<j) i++;
 27             if(i<j) swap(b[i],b[j]);
 28         }
 29         b[l]=b[i];b[i]=t;
 30         qsort(l,i-1);
 31         qsort(i+1,r);
 32     }
 33 }
 34 int binarysearch(int l,int r,int val)//二分查找,未找到返回-1
 35 {
 36     int mid,ans=-1;
 37     while(l<=r)
 38     {
 39         mid=(l+r)>>1;
 40         if(val>c[mid]) l=mid+1;
 41         else if(val==c[mid]) return mid;
 42         else r=mid-1;
 43     }
 44     return ans;
 45 }
 46
 47 void build(int l,int r,int rt)
 48 {
 49     sum[rt] = 0;
 50     if(l == r)
 51         return ;
 52     int mid = (l + r)>>1;
 53     build(lson);
 54     build(rson);
 55 }
 56 void updata(int pos,int v,int l,int r,int rt)
 57 {
 58     if(l == r)
 59     {
 60         sum[rt]=v;
 61         return ;
 62     }
 63     int mid = (l + r)>>1;
 64     if(pos <= mid)
 65         updata(pos,v,lson);
 66     else
 67         updata(pos,v,rson);
 68     sum[rt]=(sum[rt<<1]>sum[rt<<1|1]?sum[rt<<1]:sum[rt<<1|1]);
 69 }
 70 int query(int L,int R,int l,int r,int rt)
 71 {
 72     if(L <= l && R >= r)
 73     {
 74         return sum[rt];
 75     }
 76     int mid = (l + r)>>1;
 77     int ans;
 78     if(L <= mid)
 79         ans = query(L,R,lson);
 80     if(R > mid)
 81         ans = max(ans,query(L,R,rson));
 82     return ans;
 83 }
 84
 85 int main()
 86 {
 87     int n,i;
 88     while(scanf("%d",&n),n)
 89     {
 90         for(i=1;i<=n;i++)
 91         {
 92             scanf("%d",a+i);b[i]=a[i];
 93         }
 94         qsort(1,n);
 95         int cnt=1;c[1]=b[1];
 96         for(i=2;i<=n;i++) if(b[i]!=b[i-1])//离散化去重
 97             c[++cnt]=b[i];
 98         build(1,cnt,1);
 99         int x,maxv,ans=0;
100         for(i=1;i<=n;i++)
101         {
102             x=binarysearch(1,cnt,a[i]);
103             if(x>1)
104             {
105                 maxv=query(1,x-1,1,cnt,1);
106                 updata(x,maxv+a[i],1,cnt,1);
107             }
108             else
109             {
110                 maxv=0;
111                 updata(x,maxv+a[i],1,cnt,1);
112             }
113             if(maxv+a[i]>ans) ans=maxv+a[i];
114         }
115         printf("%d\n",ans);
116     }
117     return 0;
118 }
时间: 2024-10-12 09:27:25

hdu 1087 最大上升子序列的和(dp或线段树)的相关文章

hdu 1087 最大上升子序列和

题意:求最大上升子序列和 #include<iostream> using namespace std; int main() { int n,a[1001],b[1001],max; while(cin>>n&&n!=0) { for(int i=1;i<=n;i++) cin>>a[i]; b[1]=a[1]; for(i=2;i<=n;i++) { max=0; for(int j=1;j<i;j++) if(a[i]>a[

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前

HDU 5023 A Corrupt Mayor&#39;s Performance Art (线段树)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 255    Accepted Submission(s): 114 Problem Description Corrupt governors always find ways to get dirty money.

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树+优美的位运算)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this

hdu - 5023 - A Corrupt Mayor&#39;s Performance Art(线段树)

题意:一长由N小段组成的长条,每小段的初始颜色为2.现执行M个操作,每个操作是以下两种中的一种(0 < N <= 1,000,000; 0<M<=100,000) : P a b c --> 将段a到段b涂成颜色c,c是1, 2, ... 30中的一种(0 < a<=b <= N, 0 < c <= 30). Q a b --> 问段a到段b之间有哪几种颜色,按颜色大小从小到大输出(0 < a<=b <= N, 0 <

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 )

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 ) 题意: 首先是这题题意理解错误,,其次是这题无法理解状态... 已经不是英文有多烂的情况了,是中文没学好啊.....大学不学语文才是真正的硬伤啊 题目意思 有一个城堡有很多层楼, 每层楼有2个门,每个门里面又有两个楼梯,可以通往上一层的两个门 问,从x层楼到y层楼有多少中方法(不能返回) 具体看图吧,,,已经不会说话了 1 #include <cstdio> 2 #include <cstri

HDOJ/HDU 1087 Super Jumping! Jumping! Jumping!(经典DP~)

Problem Description Nowadays, a kind of chess game called "Super Jumping! Jumping! Jumping!" is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now. The game can be played by two or more t

HDU 4521 小明系列问题——小明序列 (线段树维护DP)

题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include

hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)

小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1553    Accepted Submission(s): 457 Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,但是也就由于这样,小明差点儿已经玩遍各种序列问题了.可怜的小明苦苦地在各大站点上寻找着新的序列问题,但是找来

【CF675E】Trains and Statistic(贪心,DP,线段树优化)

题意:a[i]表示从第i个车站可以一张票到第[i+1,a[i]]这些车站;p[i][j]表示从第i个车站到第j个车站的最少的票数,现在要求∑dp[i][j](1<=i<=n,i<j<=n); 思路:从I开始走,在i+1到a[i]之间一定会到使a[j]最大的j,因为要使步数最小,接下来能走得更快 区间询问最值用RMQ与线段树都可以 dp[i]表示dp[i,i+1],dp[i,i+2]...dp[i,n]这些值的和 dp[i]=dp[k]+(n-i)-(a[i]-k),k为[i+1,a