【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;
}
View Code

 

posted @ 2015-10-10 19:05  mithrilhan  阅读(143)  评论(0编辑  收藏  举报