HDOJ 5324 Boring Class 树套树
2015-08-05 13:41
806 查看
Boring Class
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 798 Accepted Submission(s): 210
[align=left]Problem Description[/align]
Mr. Zstu and Mr. Hdu are taking a boring class , Mr. Zstu comes up with a problem to kill time, Mr. Hdu thinks it’s too easy, he solved it very quickly, what about you guys?
Here is the problem:
Give you two sequences L1,L2,...,Ln
and R1,R2,...,Rn.
Your task is to find a longest subsequence v1,v2,...vm
satisfies
v1≥1,vm≤n,vi<vi+1
.(for i from 1 to m - 1)
Lvi≥Lvi+1,Rvi≤Rvi+1(for
i from 1 to m - 1)
If there are many longest subsequence satisfy the condition, output the sequence which has the smallest lexicographic order.
[align=left]Input[/align]
There are several test cases, each test case begins with an integer n.
1≤n≤50000
Both of the following two lines contain n integers describe the two sequences.
1≤Li,Ri≤109
[align=left]Output[/align]
For each test case ,output the an integer m indicates the length of the longest subsequence as described.
Output m integers in the next line.
[align=left]Sample Input[/align]
5
5 4 3 2 1
6 7 8 9 10
2
1 2
3 4
[align=left]Sample Output[/align]
5
1 2 3 4 5
1
1
强大的树套树!!!!
题意是A数组递增,B数组递减的LCS
用树状数组维护A数组的有序性,然后在树状数组的每个节点都挂一棵Treap就行。
总结:
这题在做的时候写的很慢,参照网上的大神的代码还是不知道怎么下手,也许是因为这是我写的第一个树套树代码吧,总之写了好久。在写的过程中,我发现了好多问题,还是要提一提。
1、在写Treap时我一直用的是指针,一直没注意分配的空间,导致MLE了好几发,后来才知道,指针的空间可以事先申请好,也就是开个数组,那样就不用担心已分配的内存无法释放了。
2、对于B数组的实现,我是没有注意太多的,以至于写完后发现写反了,好在这题可以用-B扑救
3、对于Treap的更新操作有好多都不及时,导致出现错误
4、对于答案相同的状态,实现并没有考虑明白
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define maxn 50005 int n; int id[maxn]; struct Point { int x,y,z; bool operator<(Point const &a)const{return y==a.y?x<a.x:y<a.y;} }a[maxn]; bool cmp(Point a,Point b){return a.x<b.x;} struct Node{ //Treap信息 Node *son[2]; int rank; //节点信息 int key;//z轴 int id,len; //最佳信息 int bid,blen; bool operator<(const Node &a)const{return rank<a.rank;} int cmp(int x)const{if(x==key)return -1;return x<=key?0:1;} void maintain()//更新节点的最佳信息 { blen = len,bid = id; if(blen<son[0]->blen)blen = son[0]->blen,bid = son[0]->bid; if(blen<son[1]->blen)blen = son[1]->blen,bid = son[1]->bid; } void initial() { rank =key=id=len=bid=blen = 0; } }; Node *null = new Node(); struct Treap{ Node node[maxn*30]; int cntnode; void initial(){cntnode = 0;} Node* newNode() { node[++cntnode].initial(); node[cntnode].son[0] = node[cntnode].son[1] = null; return &node[cntnode]; } void rotate(Node* &o,int d) { Node* k = o->son[d^1];o->son[d^1] = k -> son[d];k->son[d] = o; o->maintain();k->maintain();o = k;//注意,必须先维护o再维护k,因为o是子节点,不优先维护,会导致父节点出错 } void ins(Node* &o,int x,int id,int len)//x为键值,p为带插入节点 { if(o==null) { o = newNode(); o->id = id; o->len = len; o->rank = rand(); o->bid = o->id;o->blen = o->len; o->key = x;o->son[0] = o->son[1] = null; }//将节点添加入平衡树中,当前节点为空时,直接插入 else { int d = o->cmp(x); if(d == -1) { if(len > o->len || len == o->len && id < o->id) { o->len = len; o->id = id; o->maintain(); return; } } ins(o->son[d],x,id,len); o->maintain();//插入后,需要维护 if(o < o->son[d]) rotate(o,d^1);//当位于左儿子时,需要进行的是右旋,当位于右儿子时应当进行左旋,因此通项为rotate(o,d^1) } } Node search(Node* &o,int v2) { //cout<<"Treap::search"<< o->id << endl; if(o == null) { return Node(); } if(v2 < o->key) return search(o->son[0],v2); else { Node tmp = Node(); tmp.id= o->id; tmp.len = o->len; if(o->son[0]->blen>tmp.len || o->son[0]->blen == tmp.len && o->son[0]->bid < tmp.id) { tmp.len = o->son[0]->blen; tmp.id = o->son[0]->bid; } Node tmp1 = search(o->son[1],v2); if(tmp1.len>tmp.len||tmp1.len == tmp.len && tmp.id>tmp1.id) tmp = tmp1; return tmp; } } }treap; struct { Node *fwt[maxn]; int N; int lowbit(int x) {return x&(-x);} void initial(int n){N = n;for(int i = 0;i<=n;i++)fwt[i] = null;} void ins(int v1,int v2,Node p)//插入操作 { while(v1<=N) { //cout<<v1<<endl; treap.ins(fwt[v1],v2,p.id,p.len); v1+=lowbit(v1); } } Node search(int v1,int v2)//树状数组查找操作,获得最优转移操作 { Node ans = Node(); Node tmp;//只需要id和len就行 while(v1!=0) { tmp = treap.search(fwt[v1],v2); //cout<<"BIT::search "<<v1<<","<<tmp.id<<endl; if(ans.len<tmp.len || ans.len == tmp.len && ans.id>tmp.id) ans = tmp; v1-=lowbit(v1); } ans.len++;//处理好答案再返回结果 return ans; } }BIT; void print(Node ans) { printf("%d\n",ans.len); int t = ans.id; while(id[t]) { printf("%d ",t); t = id[t]; } printf("%d\n",t); } int main() { #ifdef ACBang freopen("1009.in","r",stdin); freopen("1.out","w",stdout); #endif // ACBang while(~scanf("%d",&n)) { /*------读入加y轴离散化------*/ treap.initial(); for(int i = 1;i<=n;i++){a[i].x= i;scanf("%d",&a[i].y);} for(int i = 1;i<=n;i++){scanf("%d",&a[i].z);a[i].z = -a[i].z;} sort(a+1,a+n+1); int m = 0;id[1] = ++m; for(int i = 2;i<=n;i++)if(a[i].y == a[i-1].y) id[i] = m;else id[i]=++m; for(int i=1;i<=n;i++)a[i].y = id[i]; sort(a+1,a+n+1,cmp); BIT.initial(m+1); /*---------------------------------*/ Node ans = Node();//保存最后结果 Node tmp; for(int i = n;i>=1;i--)//y轴要满足逆序,所以倒着做 { //cout<<"do i"<<endl; tmp = BIT.search(a[i].y,a[i].z); // cout<<"The answer of "<<i<<" is "<<tmp.id<<" "<<treap.cntnode<<endl; id[i] = tmp.id; tmp.id = i; tmp.key = a[i].z; if(ans.len<=tmp.len) ans = tmp; BIT.ins(a[i].y,a[i].z,tmp); } print(ans); } return 0; }
相关文章推荐
- hdu4585 shaolin Treap
- HDOJ1166 敌兵布阵 树状数组
- POJ 1201 Intervals 差分约束
- HDU 5304 Eastest Magical Day Seep Group's Summer
- HNU-Flight Boarding Optimization的一些感想
- Gym 100886G Maximum Product
- HDU - 1693 Eat the Trees 插头dp
- POJ Problem 3931 Classmates题解
- POJ Problem 1089 Intervals
- POJ Problem 3941 Expected Allowance
- POJ Problem 3940 Grey Area
- POJ Problem 3910 Build Your Home
- POJ Problem 1664 放苹果
- POJ Problem 3278 Catch That Cow
- POJ Problem 2533 Longest Ordered Subsequenc
- POJ Problem 1017 Packets
- POJ Problem 2406 Power Strings
- Gym - 100814A Arcade Game
- Gym - 100814D Frozen Rivers
- Gym - 100814G It is all about wisdom