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