UVALive - 6667 Longest Chain CDQ3维问题
题意:现在有一个点堆, 一开始先给你m个点,然后再用题目中的rand函数生成剩下的n个点,问在这个点堆中可以找到的最长严格递增序列的长度是多少。
题解:
很常见的一个3维CDQ。
先按照z轴 sort 一遍,然后对于当前的序列去cdq分治。对于CDQ的每一层来说,都是用左边的点的值去更新右边点的值,对于每一层来说, 我们按照x轴sort, sort的时候注意,当同x的时候,一定是右边的询问点要在左边的修改点前面, 不然就不能保证前面的都是合法点, 对于每一个添加点来说,我们在其y轴对应的位置更新他的长度值, 对于每一个询问点来说, 我们在查询其y轴对应的位置的下面的地方去询问最长值。
但是题目中要求的是严格递增序列。
我们发现,会有中间的那一部分存在同z值的情况导致,中间偏左的点不能去更新中间偏右的点,但是我们可以发现,这个情况只会出现一个位置,对于每一次分治来说,那么我们开2个树状数组,去维护这个东西,一个梳妆数组存下左边的所有的更新点的值, 另一个梳妆数组维护 除去前面中间偏左不能维护中间偏右的那些点以外的值。
代码:
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 = 3e5 + 100; 20 int ans[N]; 21 int a, b, C = ~(1<<31), M = (1<<16)-1; 22 int r(){ 23 a = 36969 * (a & M) + (a >> 16); 24 b = 18000 * (b & M) + (b >> 16); 25 return (C&((a<<16)+b)) % 1000000; 26 } 27 struct Node{ 28 int id, x, y, z; 29 }q[N], tmp[N]; 30 bool cmp1(Node & n1, Node & n2){ 31 return n1.z < n2.z; 32 } 33 bool cmp2(Node & n1, Node & n2){ 34 if(n1.x != n2.x) return n1.x < n2.x; 35 return n1.id > n2.id; 36 } 37 int yyy[N]; 38 int tree[2][N]; 39 void Add(int x, int val, int op){ 40 for(int i = x; i < N; i+=i&(-i)) 41 tree[op][i] = max(tree[op][i], val); 42 return ; 43 } 44 int query(int x, int op){ 45 int ret = 0; 46 for(int i = x; i > 0; i -= i&(-i)) 47 ret = max(tree[op][i], ret); 48 return ret; 49 } 50 void Clear(int x, int op){ 51 for(int i = x; i < N; i+=i&(-i)) 52 tree[op][i] = 0; 53 return ; 54 } 55 void cdq(int l,int r){ 56 if(l == r) { 57 ans[l] = max(ans[l], 1); 58 return ; 59 } 60 int m = l+r >> 1; 61 cdq(l, m); 62 for(int i = l; i <= r; i++) 63 tmp[i] = q[i]; 64 int midz = q[m+1].z; 65 sort(tmp+l, tmp+r+1, cmp2); 66 for(int i = l; i <= r; i++){ 67 if(tmp[i].id <= m){ 68 Add(tmp[i].y,ans[tmp[i].id],0); 69 if(tmp[i].z != midz) Add(tmp[i].y,ans[tmp[i].id],1); 70 } 71 else{ 72 int val; 73 if(tmp[i].z != midz) val = query(tmp[i].y-1, 0); 74 else val = query(tmp[i].y-1,1); 75 ans[tmp[i].id] = max(ans[tmp[i].id], val+1); 76 } 77 } 78 for(int i = l; i <= r; i++){ 79 if(tmp[i].id <= m){ 80 Clear(tmp[i].y, 0); 81 if(tmp[i].z != midz) Clear(tmp[i].y,1); 82 } 83 } 84 cdq(m+1, r); 85 } 86 int main(){ 87 int m, n, A, B; 88 while(~scanf("%d%d%d%d", &n, &m, &A, &B) && n+m+A+B){ 89 a = A, b = B; 90 for(int i = 1; i <= n; i++){ 91 scanf("%d%d%d", &q[i].x, &q[i].y, &q[i].z); 92 yyy[i] = q[i].y; 93 } 94 for(int i = n+1; i <= n+m; i++){ 95 q[i].x = r(); q[i].y = r(); q[i].z = r(); 96 yyy[i] = q[i].y; 97 } 98 sort(yyy+1, yyy+1+n+m); 99 sort(q+1, q+1+n+m, cmp1); 100 int ysz = unique(yyy+1,yyy+1+n+m) - yyy - 1; 101 for(int i = 1; i <= n+m; i++){ 102 q[i].id = i; 103 q[i].y = lower_bound(yyy+1,yyy+1+ysz,q[i].y) - yyy; 104 ans[i] = 1; 105 } 106 cdq(1, n+m); 107 int fans = 0; 108 for(int i = 1; i <= n+m; i++) 109 fans = max(fans, ans[i]); 110 printf("%d\n", fans); 111 } 112 return 0; 113 }