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] = node{i, 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; }
如需转载,请注明出处
如有侵权,联系删除
2290713181@qq.com
如有侵权,联系删除
2290713181@qq.com