题意:
给你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 ",ans.first,ans.second%mod); 68 } 69 return 0; 70 }