【NOIP2013提高组】花匠

Description

花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。
具体而言,栋栋的花的高度可以看成一列整数h_1, h_2, … , h_n。设当一部分花被移走后,剩下的花的高度依次为g_1, g_2, … , g_m,则栋栋希望下面两个条件中至少有一个满足:
条件 A:对于1≤i≤m/2,g2i>g2i-1,同时对于1≤i

Solution

其实题目就是想找一个最长的波浪形队列。

DP

很显然,处理一个f[i]和g[i]就好了。
a[i]>a[k]:f[i]=max(g[k]+1,f[i]);a[i]

线段树优化

因为我要找的是一个位置,而且有值域的限制,所以可以用权值线段树。
直接打一个权值线段树维护最大值就好了。

离散化

如果怕空间爆了,可以用离散化,虽然不用都可以。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
const int maxn=100007;
const int zuida=1000000;
struct node{
    int fda,gda;
}t[zuida];
struct nod{
    int a,b;
}b[maxn];
using namespace std;
int i,j,k,l,n,m,ans,tot;
int a[maxn],f[maxn],g[maxn];
void insert(int x,int l,int r,int y,int z,int p){
    if(l==r){
        if(p==1)t[x].fda=max(t[x].fda,z);
        else t[x].gda=max(t[x].gda,z);    
    }
    else{
        int mid=(l+r)/2;
        if(y<=mid)insert(x*2,l,mid,y,z,p);else insert(x*2+1,mid+1,r,y,z,p);
        if(p==1)t[x].fda=max(t[x*2].fda,t[x*2+1].fda);
        else t[x].gda=max(t[x*2].gda,t[x*2+1].gda); 
    }
}
int find(int x,int l,int r,int y,int z,int p){
    if(y>z)return 0;
    if(l==y&&r==z){
        if(p==1)return t[x].fda;
        else return t[x].gda;
    }
    else{
        int mid=(l+r)/2;
        if(z<=mid)return find(x*2,l,mid,y,z,p);else if (y>mid)return find(x*2+1,mid+1,r,y,z,p);
        else{
            return max(find(x*2,l,mid,y,mid,p),find(x*2+1,mid+1,r,mid+1,z,p));
        }
    }
}
bool cmp(nod x,nod y){
    return x.aint main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&b[i].a);b[i].b=i;
    }
    sort(b+1,b+1+n,cmp);
    a[b[1].b]=1;tot=1;
    fo(i,2,n){
        if(b[i-1].a==b[i].a)a[b[i].b]=tot;
        else a[b[i].b]=++tot;
    }
    f[1]=g[1]=1;
    insert(1,1,tot,a[1],f[1],1);
    insert(1,1,tot,a[1],g[1],2);
    fo(i,2,n){
        f[i]=find(1,1,tot,1,a[i]-1,2)+1;
        g[i]=find(1,1,tot,a[i]+1,tot,1)+1;
        insert(1,1,tot,a[i],f[i],1);
        insert(1,1,tot,a[i],g[i],2);
        ans=max(ans,f[i]);
        ans=max(ans,g[i]);
    }
    printf("%d\n",ans);
}

你可能感兴趣的:(noip,DP,线段树,函数式线段树)