zoj 2319 Beautiful People

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1319

这题给人的第一感觉就是最长上升子序列,按S排序,对B进行求解最长上升子序列,但是N太大

o(n^2)肯定不行,所以要用优化,我是用了线段数进行优化。

不是经常用类,这次用了一下,还是有很多小问题的,如果在函数内部静态申请一个局部变量对象

由于对象内有很大的数组,这样就相当于在函数所占用的栈区内申请了很大数组,没有语法错误,但c++是不允许它执行的

换成从堆区申请就好了,不过要记得delete否则会超内存

DP思想+线段树优化

代码:

#include<iostream>

#include<cmath>

#include<cstdio>

#include<string>

#include<cstring>

#include<vector>

#include<stack>

#include<queue>

#include<set>

#include<map>

#include<algorithm>



#define LL long long



using namespace std;



const int N=100005;

struct node

{

    int x,y;

    int index;

}man[N];

map<int,int>mt;

stack<int>st;

int Max[N],f[N];

class segTree

{

    public:

    segTree(int s,int e)

    {

        build(s,e);

    }

    private:

    struct node

    {

        int l,r,k;

    }tree[N*4];

    public:

    void build(int l,int r,int x=1)

    {

        tree[x].l=l;

        tree[x].r=r;

        tree[x].k=0;

        if(l==r)

        return ;

        int mid=(l+r)>>1;

        build(l,mid,(x<<1));

        build(mid+1,r,((x<<1)|1));

    }

    void insert(int p,int k,int x=1)

    {

        if(Max[tree[x].k]<Max[k])

        tree[x].k=k;

        if(tree[x].l==tree[x].r)

        return ;

        if(p<=((tree[x].l+tree[x].r)>>1))

        insert(p,k,(x<<1));

        else

        insert(p,k,((x<<1)|1));

    }

    int getMax(int l,int r,int x=1)

    {

        if(tree[x].l==l&&tree[x].r==r)

        return tree[x].k;

        int mid=(tree[x].l+tree[x].r)>>1;

        if(r<=mid)

        return getMax(l,r,(x<<1));

        else if(l>mid)

        return getMax(l,r,((x<<1)|1));

        else

        {

            int k1=getMax(l,mid,(x<<1));

            int k2=getMax(mid+1,r,((x<<1)|1));

            return (Max[k1]>Max[k2])?k1:k2;

        }

    }

};

bool cmpx(node a,node b)

{

    if(a.x==b.x)

    return a.y<b.y;

    return a.x<b.x;

}

bool cmpy(node a,node b)

{

    if(a.y==b.y)

    return a.x<b.x;

    return a.y<b.y;

}

int main()

{

    //freopen("data.in","r",stdin);

    int T;

    cin>>T;

    while(T--)

    {

        int n;

        cin>>n;

        for(int i=1;i<=n;++i)

        {

            cin>>man[i].x>>man[i].y;

            man[i].index=i;

        }

        sort(man+1,man+n+1,cmpy);

        mt.clear();

        int I=0;

        for(int i=1;i<=n;++i)

        if(i==1||man[i].y!=man[i-1].y)

        mt[man[i].y]=(++I);

        sort(man+1,man+n+1,cmpx);

        memset(Max,0,sizeof(Max));

        memset(f,-1,sizeof(f));

        segTree *myTree = new segTree(0,I);

        int s=0;

        for(int i=1;i<=n;++i)

        {

            int l=mt[man[i].y];

            int k=myTree->getMax(0,l-1);

            Max[i]=Max[k]+1;

            f[i]=k;

            if(Max[i]>Max[s])

            s=i;

            st.push(i);

            if(i==n||man[i].x!=man[i+1].x)

            {

                while(!st.empty())

                {

                    int tmp=st.top();st.pop();

                    myTree->insert(mt[man[tmp].y],tmp);

                }

            }

        }

        delete myTree;

        cout<<Max[s]<<endl;

        while(f[s]!=0)

        {

            cout<<man[s].index<<" ";

            s=f[s];

        }

        cout<<man[s].index<<endl;

        if(T>0)

        cout<<endl;

    }

    return 0;

}

  

你可能感兴趣的:(ZOJ)