hdu 4742 - CDQ分治 + 树状数组

版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82925776

题目链接:点击这里

解题思路:将一个轴(z轴)从小到大排序(排序过程注意x,y也要讨论).之后的问题就变成了在排序数组中找到最长上升序列问题了.

然后用CDQ分治 + 树状数组,x轴排序,y轴用树状数组维护,就ok了.

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int mx = 1e5 + 10;
const int mod = 1<<30;
typedef long long ll;
int n,ret,m;
int py[mx],cnt,siz[mx];
struct data
{
    int lon,siz;
}dat[mx],ans,dp[mx];
struct node
{
    int x,y,z;
    int id;
    bool operator < (node A)const
    {
        return x < A.x;
    }
}s[mx],tep[mx];
bool cmp(node A,node B)
{
    if(A.z==B.z){
        if(A.x==B.x) return A.y < B.y;
        return A.x < B.x;
    }
    return A.z < B.z;
}
void up(data& A,data B)
{
    if(B.lon>A.lon) A = B;
    else if(B.lon==A.lon) A.siz = (A.siz+B.siz)%mod;
}
void add(int x,int id){
    data tmp = dp[id];
    while(x<=n){
        up(dat[x],tmp);
        x += x&(-x);
    }
}
data Get(int x)
{
    data tmp = {0,0};
    while(x){
        up(tmp,dat[x]);
        x -= x&(-x);
    }
    tmp.lon++;
    return tmp;
}
void clr(int x)
{
    while(x<=n){
        dat[x].lon = dat[x].siz = 0;
        x += x&(-x);
    }
}
int Rank(int x)
{
    return lower_bound(py+1,py+m,x)-py;
}
void cdq(int l,int r)
{
    if(l==r) return ;
    int mid = (l+r)>>1;
    int i = l,j = mid + 1;
    cdq(l,mid);
    for(int k=l;k<=r;k++) tep[k] = s[k];
    sort(tep+l,tep+mid+1);
    sort(tep+mid+1,tep+r+1);
    while(j<=r){
        while(i<=mid&&tep[i].x<=tep[j].x)
        {
            add(Rank(tep[i].y),tep[i].id);
            i++;
        }
        data no = Get(Rank(tep[j].y));
        up(dp[tep[j].id],no);
        j++;
    }
    for(i=l;i<=mid&&tep[r].x>=tep[i].x;i++) clr(Rank(tep[i].y));
    cdq(mid+1,r);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ans.lon = ans.siz = 0,m = 2;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
            py[i] = s[i].y;
            dp[i].lon = 1,dp[i].siz = 1;
        }
        sort(s+1,s+1+n,cmp);
        for(int i=1;i<=n;i++) s[i].id = i;
        sort(py+1,py+1+n);
        for(int i=2;i<=n;i++) if(py[i]!=py[i-1]) py[m++] = py[i];
        cdq(1,n);
        for(int i=1;i<=n;i++) up(ans,dp[i]);
        printf("%d %d\n",ans.lon,ans.siz);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/82925776
今日推荐