1. 程式人生 > >ICPC2017網路賽(南寧)子序列最大權值(樹狀陣列+dp)

ICPC2017網路賽(南寧)子序列最大權值(樹狀陣列+dp)

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,跑一邊最長不減子序列就可以

【程式碼】:

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <iostream>
  7. #include <algorithm>
  8. #include <string>
  9. #include <queue>
  10. #include <stack>
  11. #include <vector>
  12. #include <set>
  13. #include <list>
  14. #include <map>
  15. #define mset(a,i) memset(a,i,sizeof(a))
  16. usingnamespace std;  
  17. typedeflonglong ll;  
  18. const
    int INF=0x3f3f3f3f;  
  19. constint MAX=50005;  
  20. struct tree{  
  21.     int n;  
  22.     int a[MAX],Max[MAX],Min[MAX];//Max維護最大值 ,Min最小
  23.     void init(int N)  
  24.     {  
  25.         n=N;  
  26.         for(int i=0;i<=N;i++)  
  27.             Max[i]=-(Min[i]=INF);  
  28.     }  
  29.     void update(int x,int num)//單點更新
  30.     {  
  31.         a[x]=num;  
  32.         while(x<=n)  
  33.         {  
  34.             Min[x]=Max[x]=a[x];  
  35.             int lx=x&-x;  
  36.             for(int i=1;i<lx;i<<=1)  
  37.             {  
  38.                 Max[x]=max(Max[x],Max[x-i]);  
  39.                 Min[x]=min(Min[x],Min[x-i]);  
  40.             }  
  41.             x+=x&-x;  
  42.         }  
  43.     }  
  44.     int Qmax(int x,int y)//[x,y]最大值
  45.     {  
  46.         int ans=-INF;  
  47.         while(y>=x)  
  48.         {  
  49.             ans=max(a[y], ans);  
  50.             y--;  
  51.             for(;y-(y&-y)>=x;y-=(y&-y))  
  52.                 ans=max(Max[y],ans);  
  53.         }  
  54.         return ans;  
  55.     }  
  56.     int Qmin(int x, int y)  
  57.     {  
  58.         int ans=INF;  
  59.         while(y>=x)  
  60.         {  
  61.             ans=min(a[y],ans);  
  62.             y--;  
  63.             for(;y-(y&-y)>= x; y-=(y&-y)  )  
  64.                 ans=min(Min[y],ans);  
  65.         }  
  66.         return ans;  
  67.     }  
  68. }C;  
  69. int a[303030];  
  70. int w[303030];  
  71. int main()  
  72. {  
  73.     int n=1;  
  74.     while(~scanf("%d",&a[n]))n++;n--;  
  75.     int top=0;  
  76.     for(int i=1;i<=n;i++)  
  77.     {  
  78.         if(a[i]<0)w[i]=0;  
  79.         elseif(a[i]>10000){  
  80.             a[i]-=10000;  
  81.             w[i]=5;  
  82.         }  
  83.         else w[i]=1;  
  84.         a[i]+=21000;  
  85.         top=max(top,a[i]);  
  86.     }  
  87.     C.init(top);  
  88.     for(int i=1;i<=n;i++)  
  89.     {  
  90.         int dp=w[i]+C.Qmax(1,a[i]);//查詢小的數的最大權值和
  91.         C.update(a[i],dp);//更新a[i]時的最大值
  92.     }  
  93.     printf("%d\n",C.Qmax(1,top));  
  94.     return 0;  
  95. }