Boring Class HDU - 5324 (CDQ分治)
Posted zgqblogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Boring Class HDU - 5324 (CDQ分治)相关的知识,希望对你有一定的参考价值。
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.
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.
InputThere 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
OutputFor each test case ,output the an integer m indicates the length of the longest subsequence as described.
Output m integers in the next line.
Sample Input
5 5 4 3 2 1 6 7 8 9 10 2 1 2 3 4
Sample Output
5 1 2 3 4 5 1 1
题意
给你两个序列Li,Ri,求构造一个最长的子序列,使得L递减, R递增。在保证最长的前提下要求字典序最小。(vj)
思路:
很明显的可以看出是三维偏序问题。
但是这题要求的是最长的序列,而不是对于每一个元素求解,所以需要要对CDQ分治的部分做相应的更改。
我们设对每一个元素,求以它未开始的符合题意的序列长度最长是多长。只有这样,才能顺利求出字典序最小。
那么对于每一个元素,在处理其答案时,其右侧的元素答案都应该已知了。
传统分治的做法显然不能满足这个要求,因为在如果先治左边,那么右边未知,便无法知道答案。
于是我们想到先分治右侧,再分治左侧。
但是这还不够,在对左侧求解过程中,当前右侧的答案可能并非是全局的答案,这一点的原因我不知道该如何描述,但是在3层CDQ里面就已经很明显了。
所以我们先分治右边,在处理当前层,再分治左边。
由于分治顺序的特殊性,归并排序已经不适用了,所以只能使用快排。
注意在处理左侧之前,要回复左侧原来的顺序。
#include<iostream> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #define fuck(x) clog<<#x<<" = "<<x<<endl; #define debug(a, x) clog<<#a<<"["<<x<<"] = "<<a[x]<<endl; #define lson l,mid,ls #define rson mid+1,r,rs #define ls (rt<<1) #define rs ((rt<<1)|1) using namespace std; typedef long long ll; typedef unsigned long long ull; const int loveisblue = 486; const int maxn = 100086; const int maxm = 100086; const int inf = 0x3f3f3f3f; const ll Inf = 999999999999999999; const int mod = 1000000007; const double eps = 1e-6; const double pi = acos(-1); int n; struct node int a,b,c,ans; cdq[maxn]; int mx[maxn<<2]; void update(int l,int r,int rt,int pos,int val) if(l==r) mx[rt]=val; return; int mid = (l+r)>>1; if(pos<=mid) update(lson,pos,val); else update(rson,pos,val); mx[rt]=max(mx[ls],mx[rs]); int query(int l,int r,int rt,int L,int R) if(L<=l&&R>=r) return mx[rt]; int ans = 0; int mid = (l+r)>>1; if(L<=mid) ans= max(ans,query(lson,L,R)); if(R>mid) ans = max(ans,query(rson,L,R)); return ans; int num[maxn]; int rem[maxn],tot; int get_id(int x) return lower_bound(rem+1,rem+1+tot,x)-rem; bool cmp1(node a,node b) if(a.b!=b.b)return a.b>b.b; return a.c<b.c; bool cmp(node a,node b) return a.a<b.a; void solve(int l,int r) if(l==r) return; int mid = (l+r)>>1; solve(mid+1,r); int t1 = mid,t2 = r; int cur = r+1; sort(cdq+l,cdq+mid+1,cmp1); sort(cdq+mid+1,cdq+r+1,cmp1); while (t1>=l||t2>mid) if (t1 < l || (t2 > mid && cdq[t1].b >= cdq[t2].b)) update(1, tot, 1, get_id(cdq[t2].c), cdq[t2].ans); t2--; else cdq[t1].ans = max(cdq[t1].ans, query(1, tot, 1, get_id(cdq[t1].c) ,tot)+1); t1--; for(int i=mid+1;i<=r;i++) update(1,tot,1,get_id(cdq[i].c),0); sort(cdq+l,cdq+mid+1,cmp); solve(l,mid); int main() #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d",&n)!=EOF) tot = 0; for (int i = 1; i <= n; i++) scanf("%d", &num[i]); for (int i = 1; i <= n; i++) int x; scanf("%d", &x); rem[++tot] = x; cdq[i] = nodei, num[i], x, 1; sort(rem+1,rem+1+tot); tot = unique(rem+1,rem+1+tot)-rem-1; solve(1,n); sort(cdq+1,cdq+1+n,cmp); int ans = 0; for(int i=1;i<=n;i++) ans = max(cdq[i].ans,ans); printf("%d\n",ans); int last = 0; cdq[0].b = inf; cdq[0].c = -1; for(int i=1;i<=n;i++) if(cdq[i].ans==ans&&cdq[i].b<=cdq[last].b&&cdq[i].c>=cdq[last].c) ans--; last=i; if(ans==0)printf("%d\n",i); else printf("%d ",i); return 0;
以上是关于Boring Class HDU - 5324 (CDQ分治)的主要内容,如果未能解决你的问题,请参考以下文章