Let S be a sequence of integers s1, s2, ..., sn Each integer is is associated with a weight by the following rules:
(1) If is is negative, then its weight is 0.
(2) If is is greater than or equal to 10000, then its weight is 5. Furthermore, the real integer value of si is si−10000 . For example, if si is 10101, then is is reset to 101 and its weight is 5.
(3) Otherwise, its weight is 1.
A non-decreasing subsequence of S is a subsequence si1, si2, ..., sik, with i1<i2 ... <ik, such that, for all 1≤j<k, we have sij<sij+1.
A heaviest non-decreasing subsequence of S 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:
80 75 73 93 73 73 10101 97 −1 −1 114 −1 10113 118
The heaviest non-decreasing subsequence of the sequence is <73,73,73,101,113,118> with the total weight being 1+1+1+5+5+1=14. Therefore, your program should output 14 in this example.
We guarantee that the length of the sequence does not exceed 2∗105
Input Format
A list of integers separated by blanks:s1, s2,...,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
题目来源
负数不用考虑 直接去掉就可以,
问非递减序列, 中 权值最大是多少;
刚开始理解错了 用到而是 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