HDU5324 Boring Class

来源:互联网 发布:python open nameerror 编辑:程序博客网 时间:2024/05/19 03:20

题目链接

题目大意

给定n个元素, 每个元素有两个权值ai,bi,要求取出一个子序列使得取出的ai不严格递减,bi不严格递增,输出最大的子序列长度以及字典序最小的方案.
n5×104,1ai,bi109.

题解

可以先把bi的值取相反数.
然后容易写出一个朴素的dp,因为要求字典序最小我们可以从右往左dp.

dp[i]=maxj>i,aj<ai,bj<bi{dp[j]}+1.
时先把右半部分的dp值算出来,然后用它们更新左半部分的dp值.这样计算是不会有遗漏的(所有dp值的初值为1).这样就去掉了一维下标,我们再将更新和询问按一个维度的权值排序,这样又去掉了一维,最后一维依旧用树状数组维护.
两种做法的复杂度都是O(nlg2n)的.

树状数组套树状数组

#include<cstdio>#include<cstring>#include<vector>#include<iostream>#include<algorithm>#define lowbit(x) (x&-x)using namespace std;const int N=5e4+5;int A[N],B[N],num_A[N],dp[N],nxt[N];inline void Max(int &a,int b){    if(a==-1||dp[a]<dp[b]||dp[a]==dp[b]&&b<a)a=b;}struct BIT{    vector<int>num,bit;    BIT(){        num.clear();        bit.clear();    }    void init(){        sort(num.begin(),num.end());        num.erase(unique(num.begin(),num.end()),num.end());        bit.resize(num.size()+1);        for(int i=1;i<=num.size();++i)            bit[i]=-1;    }    void update(int tar,int val){        tar=lower_bound(num.begin(),num.end(),tar)-num.begin()+1;        while(tar<=num.size()){            Max(bit[tar],val);            tar+=lowbit(tar);        }    }    int query(int tar){        tar=upper_bound(num.begin(),num.end(),tar)-num.begin();        int res=-1;        while(tar){            Max(res,bit[tar]);            tar-=lowbit(tar);        }        return res;    }}Bit[N];void rd(int &res){    res=0;    char c;    while(c=getchar(),c<48);    do res=(res<<3)+(res<<1)+(c^48);        while(c=getchar(),c>47);}void solve(int n){    int tot_A=0,ans=0,st;    for(int i=1;i<=n;++i){        rd(A[i]);        num_A[tot_A++]=A[i];    }    for(int i=1;i<=n;++i){        rd(B[i]);        B[i]*=-1;    }    sort(num_A,num_A+tot_A);    tot_A=unique(num_A,num_A+tot_A)-num_A;    for(int i=n;i;--i){        int tar=A[i]=lower_bound(num_A,num_A+tot_A,A[i])-num_A+1;        while(tar<=tot_A){            Bit[tar].num.push_back(B[i]);            tar+=lowbit(tar);        }    }    for(int i=1;i<=tot_A;++i)        Bit[i].init();    for(int i=n;i;--i){        int tar=A[i],res=-1;        while(tar){            Max(res,Bit[tar].query(B[i]));            tar-=lowbit(tar);        }        if(~res)dp[i]=dp[res]+1;        else dp[i]=1;        nxt[i]=res;        if(dp[i]>=ans){            ans=dp[i];            st=i;        }        tar=A[i];        while(tar<=tot_A){            Bit[tar].update(B[i],i);            tar+=lowbit(tar);        }    }    printf("%d\n",ans);    bool first=true;    for(int cur=st;~cur;cur=nxt[cur],first=false){        if(!first)putchar(' ');        printf("%d",cur);    }    putchar('\n');}int main(){    int n;    while(~scanf("%d",&n))solve(n);    return 0;}

分治+树状数组

#include<cstdio>#include<cstring>#include<algorithm>#define lowbit(x) (x&-x)using namespace std;const int N=5e4+5;int n,tot_A,A[N],B[N],num_A[N],dp[N],bit[N];struct Ope{    int x,y,id;    bool type;    inline bool operator <(const Ope &tmp)const{        if(y!=tmp.y)return y<tmp.y;        return type<tmp.type;    }}ope[N];inline void chk_Max(int &a,int b){    if(~b&&(a==-1||dp[a]<dp[b]||dp[a]==dp[b]&&b<a))a=b;}inline void Max(int &a,int b){    if(b>a)a=b;}void rd(int &res){    res=0;    char c;    while(c=getchar(),c<48);    do res=(res<<3)+(res<<1)+(c^48);        while(c=getchar(),c>47);}int query(int tar){    int res=-1;    while(tar){        chk_Max(res,bit[tar]);        tar-=lowbit(tar);    }    return res;}void update(int tar,int val){    while(tar<=tot_A){        chk_Max(bit[tar],val);        tar+=lowbit(tar);    }}void rec(int L,int R){    if(L==R)return;    int mid=L+R>>1;    rec(mid+1,R);    int cnt=0;    for(int i=L;i<=mid;++i)        ope[cnt++]=(Ope){A[i],B[i],i,1};    for(int i=mid+1;i<=R;++i)        ope[cnt++]=(Ope){A[i],B[i],i,0};    sort(ope,ope+cnt);    for(int i=0;i<cnt;++i){        if(ope[i].type){            int res=query(ope[i].x);            if(~res)Max(dp[ope[i].id],dp[res]+1);        }        else update(ope[i].x,ope[i].id);    }    for(int i=0;i<cnt;++i){        if(ope[i].type)continue;        while(ope[i].x<=tot_A){            bit[ope[i].x]=-1;            ope[i].x+=lowbit(ope[i].x);        }    }    rec(L,mid);}void solve(){    tot_A=0;    for(int i=1;i<=n;++i){        dp[i]=1;        rd(A[i]);        num_A[tot_A++]=A[i];    }    for(int i=1;i<=n;++i){        rd(B[i]);        B[i]*=-1;    }    sort(num_A,num_A+tot_A);    tot_A=unique(num_A,num_A+tot_A)-num_A;    for(int i=1;i<=n;++i){        A[i]=lower_bound(num_A,num_A+tot_A,A[i])-num_A+1;    }    rec(1,n);    int ans=0;    for(int i=1;i<=n;++i)        Max(ans,dp[i]);    printf("%d\n",ans);    int pre=-1;    for(int i=1;i<=n;++i){        if(dp[i]==ans&&(pre==-1||A[i]<=A[pre]&&B[i]<=B[pre])){            pre=i;            printf("%d%c",i," \n"[ans==1]);            if(!--ans)return;        }    }}int main(){    memset(bit,-1,sizeof(bit));    while(~scanf("%d",&n))solve();    return 0;}
1 0
原创粉丝点击