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;
}

  

原文地址:https://www.cnblogs.com/liulangye/p/3055800.html