Hdu 5324 Boring Class (cdq分治)

来源:互联网 发布:安正时尚集团 知乎 编辑:程序博客网 时间:2024/05/17 23:42

解析:因为是最小字典序,所以从右往左DP。

dp[i] = max(dp[j]+1) i < j,L[i]>=L[j],R[i]<=R[j]

因为这是三维上的问题,自然的就能想到cdq分治了。

在一个区间[l,r]内,先对[mid+1,r]递归,按L[]排序后建立一个对R的线段树,来计算[mid+1,r]的影响,再递归[l,r]。

这里说的比较笼统,不过熟悉cdq分治的同学应该能立马明白我说的什么吧!

[code]:

#include<cstdio>#include<cstring>#include<algorithm>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int maxn = 1e5+5;int mc[2*maxn],hah;int n,L[maxn],R[maxn],dp[maxn],pre[maxn];int C[8*maxn];int que[maxn];void init(){    hah = 0;    memset(pre,-1,(n+1)*sizeof(int));}void push_up(int rt){    if(dp[C[rt<<1]] != dp[C[rt<<1|1]]){        C[rt] = dp[C[rt<<1]]>dp[C[rt<<1|1]]?C[rt<<1]:C[rt<<1|1];    }else C[rt] = min(C[rt<<1],C[rt<<1|1]);}void build(int l,int r,int rt){    C[rt] = 0;    if(l == r) return;    int mid = (l+r)>>1;    build(lson);build(rson);}void update(int k,int x,int l,int r,int rt){    if(l == r){        if(dp[x]>dp[C[rt]]) C[rt] = x;        else if(dp[x]==dp[C[rt]]) C[rt] = min(C[rt],x);        return;    }    int mid = (l+r)>>1;    if(k <= mid) update(k,x,lson);    else update(k,x,rson);    push_up(rt);}void debug(int l,int r,int rt){    if(l ==r){        printf("%d ",C[rt]);        return;    }    int mid = (l+r)>>1;    debug(lson);debug(rson);}void clr(int k,int l,int r,int rt){    C[rt] = 0;    if(l == r) return;    int mid = (l+r)>>1;    if(k <= mid) clr(k,lson);    else clr(k,rson);}int query(int a,int b,int l,int r,int rt){    if(a <= l&&r <= b) return C[rt];    if(l > b||r < a) return 0;    int p1,p2,mid = (l+r)>>1;    p1 = query(a,b,lson);p2 = query(a,b,rson);    if(dp[p1]!=dp[p2]) return dp[p1]>dp[p2]?p1:p2;    else return min(p1,p2);}bool cmp(const int &i,const int &j){    return L[i]!=L[j]?L[i]<L[j]:i > j;}void cdq(int l,int r){    if(l>=r) return;    int u,v,i,j,mid,len;    mid = (l+r)>>1;    cdq(mid+1,r);    len = 0;    for(i = l;i <= r;i++) que[len++] = i;    sort(que,que+len,cmp);    for(i = 0;i < len;i++){        u = que[i];        if(u > mid){            update(R[u],u,1,hah,1);        }else{            v = query(R[u],hah,1,hah,1);            if(!v) continue;            if(dp[u]<dp[v]+1){                dp[u] = dp[v]+1;pre[u] = v;            }else if(dp[u]==dp[v]+1) pre[u] = min(pre[u],v);        }    }    for(i = 0;i < len;i++){        if(que[i]>mid) clr(R[que[i]],1,hah,1);    }    cdq(l,mid);}int main(){    int i,j;    while(~scanf("%d",&n)){        init();        for(i = 1;i <= n;i++) scanf("%d",&L[i]);        for(i = 1;i <= n;i++) scanf("%d",&R[i]);        for(i = 1;i <= n;i++){            mc[hah++] = L[i];mc[hah++] = R[i];            dp[i] = 1;        }        sort(mc,mc+hah);        hah = unique(mc,mc+hah)-mc;        for(i = 1;i <= n;i++){            L[i] = lower_bound(mc,mc+hah,L[i])-mc+1;            R[i] = lower_bound(mc,mc+hah,R[i])-mc+1;        }        build(1,hah,1);        cdq(1,n);        int tmp = -1;        for(i = 1;i <= n;i++){            tmp = max(tmp,dp[i]);        }        for(i = 1;i <= n;i++) if(dp[i]==tmp) break;        printf("%d\n%d",dp[i],i);        while(pre[i]!=-1){            printf(" %d",pre[i]);            i = pre[i];        }        putchar('\n');    }    return 0;}


0 0
原创粉丝点击