hdu_4742_Pinball Game 3D(cdq分治+树状数组)

题目链接:hdu_4742_Pinball Game 3D

题意:

给你n个点,让你求三维的LIS,并且求出有多少种组合能达到LIS。

题解:

求三维的LIS,典型的三维偏序问题,x排序,解决一维,cdq分治y,解决一维,树状数组维护z,解决一维。

注意,cdq中sort不要调用太多,不然会被卡常。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 typedef pair<int,int>P;
 5 
 6 const int N=1e5+7,mod=1<<30;
 7 int t,n,hsh_ed,hsh[N];
 8 P sum[N],dp[N];
 9 
10 struct node
11 {
12     int x,y,z,id;
13     bool operator <(const node & b)const{return x<b.x||(x==b.x&&y<b.y)||(x==b.x&&y==b.y&&z<b.z);}
14 }a[N],b[N];
15 
16 inline void up(P &a,P b)
17 {
18     if(a.first==b.first)a.second+=b.second;
19     else if(a.first<b.first)a=b;
20 }
21 inline void add(int x,P c){while(x<=hsh_ed)up(sum[x],c),x+=x&-x;}
22 inline P ask(int x){P an=P(0,0);while(x)up(an,sum[x]),x-=x&-x;return an;}
23 inline void back(int x){while(x<=hsh_ed)sum[x]=P(0,0),x+=x&-x;}
24 
25 void cdq(int l,int r)
26 {
27     if(l==r)return;
28     int mid=l+r>>1;
29     cdq(l,mid);
30     F(i,l,r)b[i]=a[i],b[i].x=0;
31     sort(b+l,b+1+r);
32     F(i,l,r)
33     {
34         if(b[i].id<=mid)add(b[i].z,dp[b[i].id]);
35         else
36         {
37             P now=ask(b[i].z);
38             if(now.first+1>dp[b[i].id].first)dp[b[i].id]=P(now.first+1,now.second);
39             else if(now.first+1==dp[b[i].id].first)dp[b[i].id].second+=now.second;
40         }
41     }        
42     F(i,l,r)if(b[i].id<=mid)back(b[i].z);
43     cdq(mid+1,r);
44 }
45 
46 int main()
47 {
48     scanf("%d",&t);
49     while(t--)
50     {
51         scanf("%d",&n),hsh_ed=0;
52         F(i,1,n)
53         {
54             scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
55             hsh[i]=a[i].z;
56         }
57         sort(a+1,a+1+n);
58         sort(hsh+1,hsh+1+n),hsh_ed=unique(hsh+1,hsh+1+n)-hsh;
59         F(i,1,n)
60         {
61             dp[i]=P(1,1),a[i].id=i;
62             a[i].z=lower_bound(hsh+1,hsh+1+hsh_ed,a[i].z)-hsh;
63         }
64         cdq(1,n);
65         P ans=P(0,0);
66         F(i,1,n)up(ans,dp[i]);
67         printf("%d %d\n",ans.first,ans.second%mod);
68     }
69     return 0;
70 }
View Code

 

转载于:https://www.cnblogs.com/bin-gege/p/6090206.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值