HDU 5324 Boring Class CDQ分治
题目要求一个3维偏序点的最长子序列,并且字典序最小。
题解:
这种题目出现的次数特别多了。如果不需要保证字典序的话直接cdq就好了。
这里需要维护字典序的话,我们从后往前配对就好了,因为越前面的点权重越大。(对于字典序来说)
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 1e5 + 100; 20 int ans[N]; 21 int pre[N]; 22 struct Node{ 23 int l, r, id; 24 bool operator<(const Node x) const{ 25 if(r != x.r) return r > x.r; 26 return id > x.id; 27 } 28 }A[N], tmp[N]; 29 int ll[N], lsz; 30 int tree[N][2]; 31 void add(int x, int len, int id){ 32 for(int i = x; i < N; i+=i&(-i)){ 33 if(len > tree[i][0]){ 34 tree[i][0] = len; 35 tree[i][1] = id; 36 } 37 else if(len == tree[i][0]) tree[i][1] = min(tree[i][1], id); 38 } 39 } 40 pll query(int x){ 41 int len = 0, ret = 0; 42 for(int i = x; i > 0; i -= i &(-i)){ 43 if(len == tree[i][0]) ret = min(ret, tree[i][1]); 44 else if(len < tree[i][0]){ 45 len = tree[i][0]; 46 ret = tree[i][1]; 47 } 48 } 49 return pll(len, ret); 50 } 51 void clear(int x){ 52 for(int i = x; i < N; i += i&(-i)) 53 tree[i][0] = tree[i][1] = 0; 54 } 55 void cdq(int l, int r){ 56 if(l == r) return ; 57 int m = l+r >> 1; 58 cdq(m+1,r); 59 for(int i = l; i <= r; i++) 60 tmp[i] = A[i]; 61 sort(tmp+l, tmp+r+1); 62 for(int i = l; i <= r; i++){ 63 //cout << tmp[i].id << " " << tmp[i].l << " " << tmp[i].r << endl; 64 int id = tmp[i].id; 65 if(id > m) add(tmp[i].l, ans[id], id); 66 else { 67 pll p = query(tmp[i].l); 68 int len = p.fi, iid = p.se; 69 if(len == 0) continue; 70 if(len+1 > ans[id]){ 71 ans[id] = len+1; 72 pre[id] = iid; 73 } 74 else if(len + 1 == ans[id]) 75 pre[id] = min(pre[id], iid); 76 } 77 } 78 for(int i = l; i <= r; i++){ 79 if(tmp[i].id > m) clear(tmp[i].l); 80 } 81 cdq(l,m); 82 } 83 int main(){ 84 int n; 85 lsz = 0; 86 while(~scanf("%d", &n)){ 87 for(int i = 1; i <= n; i++){ 88 ans[i] = 1, pre[i] = i; 89 A[i].id = i; 90 scanf("%d", &A[i].l); 91 ll[i] = A[i].l; 92 } 93 sort(ll+1, ll+1+n); 94 lsz = unique(ll+1,ll+1+n) - ll - 1; 95 for(int i = 1; i <= n; i++){ 96 scanf("%d", &A[i].r); 97 A[i].l = lower_bound(ll+1, ll+1+lsz, A[i].l) - ll; 98 } 99 cdq(1,n); 100 int fans = 0, fid = 0; 101 for(int i = 1; i <= n; i++){ 102 if(fans < ans[i]){ 103 fans = ans[i]; 104 fid = i; 105 } 106 } 107 printf("%d\n", fans); 108 for(int i = 1; i <= fans; i++){ 109 printf("%d%c", fid, " \n"[i==fans]); 110 fid = pre[fid]; 111 } 112 113 } 114 return 0; 115 }