2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 L题 非递减权值最大

来源:互联网 发布:linux 文件不保存退出 编辑:程序博客网 时间:2024/06/02 04:14


Let SS be a sequence of integers s_{1}s1, s_{2}s2, ......, s_{n}sn 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}si is s_{i}-10000si10000 . For example, if s_{i}si 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}si1, s_{i2}si2, ......, s_{ik}sik, with i_{1}<i_{2}\ ...\ <i_{k}i1<i2 ... <ik, such that, for all 1 \leq j<k1j<k, we have s_{ij}<s_{ij+1}sij<sij+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 -11 -11 114114 -11 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}2105

Input Format

A list of integers separated by blanks:s_{1}s1, s_{2}s2,......,s_{n}sn

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 亚洲区(南宁赛区)网络赛



负数不用考虑  直接去掉就可以,  

问非递减序列, 中 权值最大是多少;

刚开始理解错了  用到而是 nlog(n)  算法找的 最长上升子序列,然后找的权值,   

但是这样不能保证权值最大;


一个很巧妙的方法就是:  权值是5     我们可以 拆分成5 个相同的数  使权值为1   这样 所有的权值都是1

就变成找 最长上升子序列了


n^n  超时

 还有一种方法就是 动态规划来做 

第二层 用树状数组来维护 前面的最大值



代码:


#include <iostream>#include <stdio.h>#include <algorithm>#include <cmath>#include <math.h>#include <cstring>#include <string>#include <queue>#include <stack>#include <stdlib.h>#include <list>#include <map>#include <set>#include <bitset>#include <vector>#define mem(a,b) memset(a,b,sizeof(a))#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define FIN      freopen("input.txt","r",stdin)#define FOUT     freopen("output.txt","w",stdout)#define S1(n)    scanf("%d",&n)#define SL1(n)   scanf("%I64d",&n)#define S2(n,m)  scanf("%d%d",&n,&m)#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)#define Pr(n)     printf("%d\n",n)using namespace std;typedef long long ll;const int INF=0x3f3f3f3f;const double esp=1e-6;const int maxn=1e6+5;const int MOD=1e9+7;const int mod=1e9+7;int dir[5][2]={0,1,0,-1,1,0,-1,0};struct node{int x,y;}a[maxn];int stacks[maxn];int main(){int x;int k=0;while((scanf("%d",&x))!=EOF){if(x<10000&&x>=0)a[k].x=x,a[k++].y=1;else if(x<0)continue;else if(x>=10000){for(int i=1;i<=5;i++)a[k].x=x-10000,a[k++].y=1;}}stacks[0]=-1;int n=k-1;int top=0;int temp;for (int i = 0; i <=n; i++)    {        temp=a[i].x;        if (temp >= stacks[top])        {            stacks[++top] = temp;        }        else           {            int low = 1, high = top;            int mid;            while(low <= high)            {                mid = (low + high) / 2;                if (temp >= stacks[mid])                {                    low = mid + 1;                }                else                {                    high = mid - 1;                }        }         stacks[low] = temp;        }    } cout<<top<<endl;return 0;}/*75 73 93 73000 10101 97 -1 102 114 -1 10113 118*/




树状数组 解法:


【代码】:

#include <iostream>#include <stdio.h>#include <algorithm>#include <cmath>#include <math.h>#include <cstring>#include <string>#include <queue>#include <stack>#include <stdlib.h>#include <list>#include <map>#include <set>#include <bitset>#include <vector>#define mem(a,b) memset(a,b,sizeof(a))#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define FIN      freopen("input.txt","r",stdin)#define FOUT     freopen("output.txt","w",stdout)#define S1(n)    scanf("%d",&n)#define SL1(n)   scanf("%I64d",&n)#define S2(n,m)  scanf("%d%d",&n,&m)#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)#define Pr(n)     printf("%d\n",n)using namespace std;typedef long long ll;const double PI=acos(-1);const int INF=0x3f3f3f3f;const double esp=1e-6;const int maxn=1e6+5;const int MAX=50005;const int MOD=1e9+7;const int mod=1e9+7;int dir[5][2]={0,1,0,-1,1,0,-1,0};ll inv[maxn*2]; void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);}}ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;}ll lcm(ll a,ll b){ return b/gcd(a,b)*a;}ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;}ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;}ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;}ll inv2(ll b){return qpow(b,MOD-2);}struct math_tree{int n;int a[MAX],Max[MAX],Min[MAX];int tree[MAX]; void init(int N){n=N;for(int i=0;i<=N;i++)Max[i]=-(Min[i]=INF);}void update(int k,int num)//单点更新 {a[k]=num;while(k<=n){tree[k]+=num;Min[k]=Max[k]=a[k];int lk=k&(-k);for(int i=1;i<lk;i<<=1){Max[k]=max(Max[k],Max[k-i]);Min[k]=min(Min[k],Min[k-i]);}k+=k&(-k);// lowbit(k)= k&(-k);}}int Sum(int k){int sum=0;while(k){sum+=tree[k];k-=k&-k;}return sum;}int Get_Sum(int x,int y){return Sum(y)-Sum(x-1);}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)//[x,y] 区间最小值{int ans=INF;while(y>=x){ans=min(a[y],ans);y--;for(;y-(y&-y)>=x;y-=(y&-y))ans=min(ans,Min[y]);}return ans;}}A;int a[maxn],b[maxn];int main(){int x;int dp;int k=1;int top=0;while(scanf("%d",&x)!=EOF){if(x<0)continue;else if(x>=10000){a[k]=x-10000;b[k]=5;}else a[k]=x,b[k]=1;top=max(a[k],top);k++;}int n=k-1;math_tree ans;ans.init(top);for(int i=1;i<=n;i++){dp=b[i]+ans.Qmax(1,a[i]);// 前a[i] 最大值 ans.update(a[i],dp);// 更新 最大值 }printf("%d\n",ans.Qmax(1,top));return 0;}


123

阅读全文
0 0
原创粉丝点击