bjoi 2010 纸箱堆叠 二维树状数组

题意:P 工厂是一个生产纸箱的工厂。纸箱生产线在人工输入三个参数 n p a , , 之后,
即可自动化生产三边边长为

(a mod P,a^2 mod p,a^3 mod P)
(a^4 mod p,a^5 mod p,a^6 mod P)
....
(a^(3n-2) mod p,a^(3n-1) mod p,a^(3n) mod p)

的n个纸箱。在运输这些纸箱时,为了节约空间,必须将它们嵌套堆叠起来。
一个纸箱可以嵌套堆叠进另一个纸箱当且仅当它的最短边、次短边和最长边
长度分别严格小于另一个纸箱的最短边、次短边和最长边长度。这里不考虑
任何旋转后在对角线方向的嵌套堆叠。 
你的任务是找出这n个纸箱中数量最多的一个子集,使得它们两两之间都可
嵌套堆叠起来。

2<=P<=2000000000,1<=a<=p-1,a^k mod p<>0,ap<=2000000000,1<=N<=50000

 

思路:先把n个纸箱求出来

按一维排序 另两维用二维树状数组

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<map>
  5 #include<cmath>
  6 #include<algorithm>
  7 using namespace std;
  8 #define MAXN 50000+100
  9 struct number
 10 {
 11     long long x,y,z;
 12 };
 13 int n,ans=0;
 14 long long t,p;
 15 long long b[MAXN];
 16 number a[MAXN];
 17 map<pair<int,int>,int> tree;
 18 map<long long,int> home;
 19 void my_sort(int i)
 20 {
 21     if(a[i].x>a[i].y) swap(a[i].x,a[i].y);
 22     if(a[i].y>a[i].z) swap(a[i].z,a[i].y);
 23     if(a[i].x>a[i].y) swap(a[i].x,a[i].y);
 24 }
 25 bool cmp(const number &A,const number &B)
 26 {
 27     if(A.x<B.x) return 1;
 28     if(A.x>B.x) return 0;
 29     if(A.y>B.y) return 1;
 30     return 0;
 31 }
 32 
 33 void make_a()
 34 {
 35     int i;
 36     long long temp=1;
 37     for(i=1;i<=3*n;i++)
 38     {
 39         temp=temp*t%p;
 40         if(i%3==1) a[i/3+1].x=temp;
 41         else if(i%3==2) a[i/3+1].y=temp;
 42         else
 43         {
 44             a[i/3].z=temp;
 45             my_sort(i/3);
 46         }
 47     }
 48     sort(a+1,a+n+1,cmp);
 49 }
 50 void discretization()
 51 {
 52     b[0]=-1;
 53     int i,j=0;
 54     for(i=1;i<=n;i++)
 55         b[i]=a[i].y;
 56     sort(b,b+n+1);
 57     for(i=1;i<=n;i++)
 58     {
 59         if(b[i]!=b[i-1])
 60             home[b[i]]=++j;
 61         else
 62             home[b[i]]=j;
 63     }
 64     for(i=1;i<=n;i++) a[i].y=home[a[i].y];
 65 
 66     for(i=1;i<=n;i++)
 67         b[i]=a[i].z;
 68     sort(b,b+n+1);
 69     j=0;
 70     for(i=1;i<=n;i++)
 71     {
 72         if(b[i]!=b[i-1])
 73             home[b[i]]=++j;
 74         else
 75             home[b[i]]=j;
 76     }
 77     for(i=1;i<=n;i++)
 78         a[i].z=home[a[i].z];
 79 }
 80 int lowbit(int x)
 81 {
 82     return x&(x^(x-1));
 83 }
 84 void update(int x,int y,int add)
 85 {
 86     for(int i=x;i<=n;i+=lowbit(i))
 87         for(int j=y;j<=n;j+=lowbit(j))
 88             tree[make_pair(i,j)]=max(tree[make_pair(i,j)],add);
 89 }
 90 int find(int x,int y)
 91 {
 92     int ans=0;
 93     for(int i=x;i>0;i-=lowbit(i))
 94         for(int j=y;j>0;j-=lowbit(j))
 95             ans=max(ans,tree[make_pair(i,j)]);
 96     return ans;
 97 }
 98 
 99 int main()
100 {
101     int temp;
102     scanf("%lld%lld%d",&t,&p,&n);
103     make_a();
104     discretization();
105     for(int i=1;i<=n;i++)
106     {
107         temp=find(a[i].y-1,a[i].z-1);
108         update(a[i].y,a[i].z,temp+1);
109         if(temp+1>ans) ans=temp+1;
110     }
111     printf("%d\n",ans);
112     return 0;
113 }

 

posted on 2012-04-10 20:16  myoi  阅读(545)  评论(0编辑  收藏  举报

导航