【CDQ】 HDU 4742 Pinball Game 3D
题意:给你n(1e5)个三元组、然后要你求这n个三元组的LIS。和这样LIS的方案数。一个三元祖a比另一个元祖b大的条件是ax>=bx,ay>=by,az>=bz
思路:
排序x去掉一维。然后我们要找到 y z。然后对于一个区间上,我们对y排序,但是在排序之前记录下此时的id排序之后,就能得到y的递增,但是此时可能打乱了x的顺序。所以我们就要利用之前记录的id,id小的也就是x小,那么此时我们就能找到xy的大小关系,然后我们将z离散化之后建一个bit树。在之前排序的y区间左子树的可以直接加进去。不用更新,因为 但是对于右子树,不仅要加进去 而且还要更新。这样x小的都去左子树了,大的都到右子树去了。而且是按照y的增序加进去的。而且后面的x一定比前面的x要大。所以这样就可以保证 x y都是有序进去的。最后在看1-z之间有多少个,更新一下就好了
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; const int mod = 1 << 30; struct Ball{ int x,y,z,idx; bool operator < (const Ball &rhs)const{ return x < rhs.x || (x == rhs.x && y < rhs.y) || (x == rhs.x && y == rhs.y && z < rhs.z); } } ball[maxn],tmpball[maxn]; struct DP{ int len,cnt; DP(){} DP(int _len,int _cnt): len(_len),cnt(_cnt) {} } dp[maxn],c[maxn]; int vec[maxn],idx; int color[maxn], C; inline int lowbit (int x){ return x & -x; } inline void update (DP &dp1, DP &dp2){ if (dp1.len < dp2.len) dp1 = dp2; else if (dp1.len == dp2.len) dp1.cnt += dp2.cnt; } inline void modify(int x,DP &d){ while (x <= idx){ if (color[x] != C) color[x] = C,c[x] = DP(0, 0); update(c[x],d); x += lowbit(x); } } DP query(int x){ DP ans = DP (0,0); while (x){ if (color[x] == C) update(ans,c[x]); x -= lowbit(x); } return ans; } inline void CLR(int x){ while (x <= idx){ c[x] = DP(0,0); x += lowbit(x); } } bool cmp(Ball a, Ball b) { if (a.y != b.y) return a.y < b.y; return a.idx < b.idx; } void CDQ (int l, int r){ if (l == r) return ; int mid = (l + r) >> 1; CDQ (l, mid); for (int i = l; i <= r; i++){ tmpball[i] = ball[i]; tmpball[i].x = 0; } sort(tmpball+l,tmpball+r+1,cmp); ++C; for (int i = l; i <= r; i++){ if (tmpball[i].idx <= mid){ modify(tmpball[i].z,dp[tmpball[i].idx]); } else { DP tmp = query(tmpball[i].z); tmp.len++; update(dp[tmpball[i].idx],tmp); } } CDQ (mid+1, r); } int main() { int T, n; scanf ("%d",&T); while (T--) { scanf ("%d",&n); for (int i = 1; i <= n; i++) { scanf ("%d%d%d",&ball[i].x, &ball[i].y, &ball[i].z); vec[i-1] = ball[i].z; } sort (ball+1, ball+n+1); sort (vec,vec+n); idx = unique(vec,vec+n) - vec; for (int i = 1; i <= n ; i++) { ball[i].z = lower_bound(vec,vec+idx,ball[i].z) - vec + 1; ball[i].idx = i; dp[i] = DP(1,1); } CDQ(1,n); DP ans = DP(0,0); for (int i = 1; i <= n ;i++) update(ans,dp[i]); printf("%d %d\n",ans.len, ans.cnt % mod); } return 0; }