[bzoj4282]慎二的随机数列
2016-10-12 11:28
267 查看
题目大意:求缺损了部分数的lis的最大可能值 n<=100000
大概是这样的
首先我们显然可以发现 我们要尽量将不知道的数塞进lis里 这样一定是最优的
因此我们可以将不知道的数去掉之后求lis 然后再把可能的数加进去
那我们怎么统计可能的数以及保证他一定能塞进去呢?
用一个类似前缀和的东西 首先你对不知道的数的情况求一个类似前缀和的东西 然后用每个数减掉他再求 最后再加上能加的不知道的数的个数
由于n很大所以要用nlogn求lis
附带一份同学的 虽然题目并不相同 但是基本上是一样的用作理解
大概是这样的
首先我们显然可以发现 我们要尽量将不知道的数塞进lis里 这样一定是最优的
因此我们可以将不知道的数去掉之后求lis 然后再把可能的数加进去
那我们怎么统计可能的数以及保证他一定能塞进去呢?
用一个类似前缀和的东西 首先你对不知道的数的情况求一个类似前缀和的东西 然后用每个数减掉他再求 最后再加上能加的不知道的数的个数
由于n很大所以要用nlogn求lis
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<iostream> #include<algorithm> #include<stack> #include<cstring> #include<set> #include<map> #include<iomanip> using namespace std; const int INF = 0x7f7f7f7f; const double pi = acos(-1.0); inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } int array[100001]; int dp[100001]; int len=0; int a[100001],n; int sumzero[100001]; int c[100001]; int main() { char str[10]; n=init(); for(int i=1;i<=n;i++) { scanf("%s",str+1); if(str[1]=='K') { a[i]=init(); sumzero[i]=sumzero[i-1]; if(len==0) { dp[++len]=a[i]-sumzero[i]; } } else { a[i]=0; sumzero[i]=sumzero[i-1]+1; } c[i]=a[i]-sumzero[i]; } int ans[100001]; ans[1]=1; int pos; for(int i=2;i<=n;i++) { if(a[i]==0) { ans[i]=len+sumzero[i]; continue; } if(c[i]>dp[len]) { dp[++len]=c[i]; } else { pos=lower_bound(dp+1,dp+1+len,c[i])-dp; dp[pos]=c[i]; } ans[i]=len+sumzero[i]; } sort(ans+1,ans+1+n); printf("%d\n",ans ); return 0; }
附带一份同学的 虽然题目并不相同 但是基本上是一样的用作理解
#include<bits/stdc++.h> using namespace std; const int maxn = 100010; int a[maxn]; int f[maxn]; int b[maxn]; int n; int mr; int find(int l,int r,int val) { int pos=0; while(l<=r) { int mid=(l+r)>>1; if(b[mid]<val) { pos=mid; l=mid+1; } else r=mid-1; } return pos; } int main() { //freopen("lis.in","r",stdin); //freopen("lis.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); memset(b,63,sizeof b); b[0]=-0x3f3f3f3f; for(int i=1;i<=n;i++) { if(a[i]==0) { b[mr+1]=b[mr]+1; for(int j=mr;j>=1;j--) if(b[j-1]+1<b[j]) b[j]=b[j-1]+1; mr++; f[i]=mr; } else { int x=find(1,i-1,a[i]); f[i]=x+1; b[x+1]=min(b[x+1],a[i]); if(f[i]>mr) mr=f[i]; } } printf("%d",mr); return 0; }
相关文章推荐
- 【bzoj4282】【慎二的随机数列】【dp】
- BZOJ 4282 慎二的随机数列 LIS
- BZOJ4282 : 慎二的随机数列
- 【BZOJ4282】慎二的随机数列(LIS)
- 【BZOJ4282】慎二的随机数列 乱搞
- [bzoj4282]慎二的随机数列_动态规划_贪心
- 【bzoj4282】慎二的随机数列
- BZOJ 4282: 慎二的随机数列|动态规划
- BZOJ4282: 慎二的随机数列
- BZOJ 4282 慎二的随机数列 动态规划
- bzoj 4282: 慎二的随机数列
- 【bzoj4282】慎二的随机数列
- bzoj 4282: 慎二的随机数列 最长不下降序列
- [BZOJ5427]最长上升子序列/[BZOJ4282]慎二的随机数列
- 4282: 慎二的随机数列 DP
- BZOJ 4287(慎二的随机数列-构造+LIS)
- 【BZOJ4282】慎二的随机数列
- [扫描线 树状数组 随机数列 优化] BZOJ 2221 [Jsoi2009]面试的考验
- [DP LIS] BZOJ 4282 慎二的随机数列
- 【JZOJ 3693】 慎二的随机数列