ICPC2017網路賽(南寧)子序列最大權值(樹狀陣列+dp)
阿新 • • 發佈:2019-01-28
Let SS be a sequence of integers s_{1}s
1 , s_{2}s
2
, ......, s_{n}s
n
Each integer is is associated with a weight by the following rules:
(1) If is is negative, then its weight is 00.
(2) If is is greater than or equal to 1000010000, then its weight is 55. Furthermore, the real integer value of s_{i}s
i
is s_{i}-10000s
i
−10000 . For example, if s_{i}s
i
is 1010110101, then is is reset to 101101 and its weight is 55.
(3) Otherwise, its weight is 11.
A non-decreasing subsequence of SS is a subsequence s_{i1}s
i1
, s_{i2}s
i2
, ......, s_{ik}s
ik
, with i_{1}<i_{2}\ ...\ <i_{k}i
1
<i
2
... <i
k
, such that, for all 1 \leq j<k1≤j<k, we have s_{ij}<s_{ij+1}s
ij
<s
ij+1
.
A heaviest non-decreasing subsequence of SS is a non-decreasing subsequence with the maximum sum of weights.
Write a program that reads a sequence of integers, and outputs the weight of its
heaviest non-decreasing subsequence. For example, given the following sequence:
8080 7575 7373 9393 7373 7373 1010110101 9797 -1−1 -1−1 114114 -1−1 1011310113 118118
The heaviest non-decreasing subsequence of the sequence is <73, 73, 73, 101, 113, 118><73,73,73,101,113,118>with the total weight being 1+1+1+5+5+1 = 141+1+1+5+5+1=14. Therefore, your program should output 1414 in this example.
We guarantee that the length of the sequence does not exceed 2*10^{5}2∗10
5
Input Format
A list of integers separated by blanks:s_{1}s
1 , s_{2}s
2 ,......,s_{n}s
n
Output Format
A positive integer that is the weight of the heaviest non-decreasing subsequence.
樣例輸入
80 75 73 93 73 73 10101 97 -1 -1 114 -1 10113 118
樣例輸出
14
題目來源
2017 ACM-ICPC 亞洲區(南寧賽區)網路賽
【題意】:
給出一組數列,負數的價值為0,,>=10000的價值為5,但值要減掉1萬,其餘的數價值為1;
問,選一個不減子序列,使得價值和最大,並輸出這個價值
【分析】:
每加入一個新元素,用前面的,小數,最大權值加上當前元素的權值,作為當前元素的最優權值。
別的隊的同學用拆點,把權值為5的點拆成5個1,跑一邊最長不減子序列就可以
【程式碼】:
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <string.h>
-
#include <time.h>
- #include <iostream>
- #include <algorithm>
- #include <string>
- #include <queue>
- #include <stack>
- #include <vector>
- #include <set>
- #include <list>
- #include <map>
- #define mset(a,i) memset(a,i,sizeof(a))
- usingnamespace std;
- typedeflonglong ll;
-
const
- constint MAX=50005;
- struct tree{
- int n;
- int a[MAX],Max[MAX],Min[MAX];//Max維護最大值 ,Min最小
- void init(int N)
- {
- n=N;
- for(int i=0;i<=N;i++)
- Max[i]=-(Min[i]=INF);
- }
- void update(int x,int num)//單點更新
- {
- a[x]=num;
- while(x<=n)
- {
- Min[x]=Max[x]=a[x];
- int lx=x&-x;
- for(int i=1;i<lx;i<<=1)
- {
- Max[x]=max(Max[x],Max[x-i]);
- Min[x]=min(Min[x],Min[x-i]);
- }
- x+=x&-x;
- }
- }
- int Qmax(int x,int y)//[x,y]最大值
- {
- int ans=-INF;
- while(y>=x)
- {
- ans=max(a[y], ans);
- y--;
- for(;y-(y&-y)>=x;y-=(y&-y))
- ans=max(Max[y],ans);
- }
- return ans;
- }
- int Qmin(int x, int y)
- {
- int ans=INF;
- while(y>=x)
- {
- ans=min(a[y],ans);
- y--;
- for(;y-(y&-y)>= x; y-=(y&-y) )
- ans=min(Min[y],ans);
- }
- return ans;
- }
- }C;
- int a[303030];
- int w[303030];
- int main()
- {
- int n=1;
- while(~scanf("%d",&a[n]))n++;n--;
- int top=0;
- for(int i=1;i<=n;i++)
- {
- if(a[i]<0)w[i]=0;
- elseif(a[i]>10000){
- a[i]-=10000;
- w[i]=5;
- }
- else w[i]=1;
- a[i]+=21000;
- top=max(top,a[i]);
- }
- C.init(top);
- for(int i=1;i<=n;i++)
- {
- int dp=w[i]+C.Qmax(1,a[i]);//查詢小的數的最大權值和
- C.update(a[i],dp);//更新a[i]時的最大值
- }
- printf("%d\n",C.Qmax(1,top));
- return 0;
- }