【题目】
【分析】
求最长不下降子序列。数据范围有点大,这就很尴尬。可以优化为nlogn的算法。
定义b[k]用来记录长度为k的不下降子序列的最末元素。首先len = 1,b[1] = a[1]。若a[i]>d[len],那么d[++len] = a[i];否则,从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],然后更新长度为j的上升子序列的最末元素,即 d[j] = a[i]。利用d的单调性,在查找j的时候可以二分查找,从而时间复杂度为nlogn。
二分函数lower_bound(l , r , x )与upper_bound(l , r , x )---l:搜索目标数据的左地址 r:搜索目标数据的右地址 x:搜索的数。lower_bound会返回第一个大于等于x的地址,uppper_bound会返回第一个大于x的地址。b[]是一个数组,所以b是一个地址,upper_bound返回的是个地址,减去b以后变成一个下标。
【代码】
#include<bits/stdc++.h>
using namespace std;
int a[200002],b[200002];
int main()
{
int n;
while(~scanf("%d",&n)){
int i,j,len=1;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
for(i=2;i<=n;i++)
if(a[i]>=b[len])
b[++len]=a[i];
else{
int t=upper_bound(b,b+len,a[i])-b;
b[t] = a[i];
}
printf("%d\n",len);
}
return 0;
}
【小声bb】
BC蛮简单的我就不说了奥...D还没补
【一元三次方程求解】
【分析】
数据比较小,-100到100,利用两根之差大于等于1,可以用枚举。然后f(a)*f(b)<0则(a,b)之间必有根,我们就可以用二分啦。
【代码】
#include<bits/stdc++.h>
using namespace std;
double a,b,c,d;
double f(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
double p(double l,double r)
{
if(r-l<=0.001) return l;
double mid=(l+r)/2;
if(f(l)*f(mid)<=0)
return p(l,mid);
else
return p(mid,r);
}
int main()
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
double ans[4];
int c=0;
for(int i=-100;i<=100;i++){
if(f(i)==0)
ans[++c]=i;
else if(f(i)*f(i+1)<0)
ans[++c]=p(i,i+1);
if(c==3) break;
}
printf("%.2lf %.2lf %.2lf\n",ans[1],ans[2],ans[3]);
return 0;
}