COGS 2479 偏序 题解

【题意】

给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数。

对于30%的数据,n<=5000。

对于100%的数据,1<=n<=50000(原题写错了哈哈),保证所有的ai、bi、ci分别组成三个1~n的排列。

【解法】

标题已经说了这是偏序,读完题,这就是个四维偏序模板题(位置一维,a,b,c剩下三维)。

解法多多,我用的是CDQ树套树(树套树写的树状数组套替罪羊树,毕竟在我的印象里替罪羊树在随机数据下跑得飞快)。

第一维已经有序,不用我们预处理,这样就可以按第一维(位置)分治,再把第二维(a)排序,剩下的第三维(b)和第四维(c)直接树套树就可以了(我用的是第三维树状数组,第四维平衡树)。

当然写CDQ套CDQ+树状数组应该也可以,然而本鶸渣不会写……

也可以写树套树套树……然而怎么写……

贴个代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define siz(x) ((x)?((x)->size):(0))
  5 #define lowbit(x) ((x)&(-(x)))
  6 using namespace std;
  7 const int maxn=50010;
  8 const double A=0.65;
  9 struct node{//Scapegoat Tree
 10     int data,size;
 11     node *lc,*rc,*prt;
 12     node(int d=0):data(d),size(1),lc(NULL),rc(NULL),prt(NULL){}
 13     inline void refresh(){size=siz(lc)+siz(rc)+1;}
 14 }*root[maxn];
 15 struct B{
 16     int id,a,b,c;
 17     bool operator<(const B &a)const{return this->a<a.a;}
 18 }a[maxn],b[maxn];
 19 void CDQ(int,int);
 20 void add(int,int);
 21 void del(int,int);
 22 int query(int,int);
 23 void insert(int);
 24 void erase(int);
 25 int rank(int);
 26 node *insert(node*);
 27 node *find(int);
 28 node *erase(node*);
 29 node *findmax(node*);
 30 void rebuild(node*);
 31 void zorder(node*);
 32 void removetree(node*);
 33 node *rebuild(int,int);
 34 int n,T,cnt,data[maxn];
 35 long long ans=0ll;
 36 int main(){
 37 #define MINE
 38 #ifdef MINE
 39     freopen("partial_order.in","r",stdin);
 40     freopen("partial_order.out","w",stdout);
 41 #endif
 42     scanf("%d",&n);
 43     for(int i=1;i<=n;i++)a[i].id=i;
 44     for(int i=1;i<=n;i++)scanf("%d",&a[i].a);
 45     for(int i=1;i<=n;i++)scanf("%d",&a[i].b);
 46     for(int i=1;i<=n;i++)scanf("%d",&a[i].c);
 47     CDQ(1,n);
 48     printf("%lld",ans);
 49 #ifndef MINE
 50     printf("\n-------------------------DONE-------------------------\n");
 51     for(;;);
 52 #endif
 53     return 0;
 54 }
 55 void CDQ(int l,int r){
 56     if(l>=r)return;
 57     int mid=(l+r)>>1;
 58     CDQ(l,mid);
 59     CDQ(mid+1,r);
 60     int i=l,j=mid+1,k=l;
 61     while(i<=mid&&j<=r){
 62         if(a[i]<a[j])b[k++]=a[i++];
 63         else b[k++]=a[j++];
 64     }
 65     while(i<=mid)b[k++]=a[i++];
 66     while(j<=r)b[k++]=a[j++];
 67     for(int i=l;i<=r;i++){
 68         a[i]=b[i];
 69         if(a[i].id<=mid)add(a[i].b,a[i].c);
 70         else ans+=query(a[i].b,a[i].c);
 71     }
 72     for(int i=l;i<=r;i++)if(a[i].id<=mid)del(a[i].b,a[i].c);
 73 }
 74 void add(int x,int d){
 75     while(x<=n){
 76         T=x;
 77         insert(d);
 78         x+=lowbit(x);
 79     }
 80 }
 81 void del(int x,int d){
 82     while(x<=n){
 83         T=x;
 84         erase(d);
 85         x+=lowbit(x);
 86     }
 87 }
 88 int query(int x,int d){
 89     int ans=0;
 90     while(x){
 91         T=x;
 92         ans+=rank(d);
 93         x-=lowbit(x);
 94     }
 95     return ans;
 96 }
 97 void insert(int x){
 98     node *rt=insert(new node(x));
 99     if(rt)rebuild(rt);
100 }
101 void erase(int x){
102     node *rt=erase(find(x));
103     if(rt)rebuild(rt);
104 }
105 int rank(int x){
106     node *rt=root[T];
107     int ans=0;
108     while(rt){
109         if(x<=rt->data)rt=rt->lc;
110         else{
111             ans+=siz(rt->lc)+1;
112             rt=rt->rc;
113         }
114     }
115     return ans;
116 }
117 node *insert(node *x){
118     if(!root[T]){
119         root[T]=x;
120         return NULL;
121     }
122     node *rt=root[T];
123     for(;;){
124         if(x->data<rt->data){
125             if(rt->lc)rt=rt->lc;
126             else{
127                 rt->lc=x;
128                 break;
129             }
130         }
131         else{
132             if(rt->rc)rt=rt->rc;
133             else{
134                 rt->rc=x;
135                 break;
136             }
137         }
138     }
139     x->prt=rt;
140     x=NULL;
141     for(;rt;rt=rt->prt){
142         rt->refresh();
143         if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
144     }
145     return x;
146 }
147 node *find(int x){
148     node *rt=root[T];
149     while(rt){
150         if(x==rt->data)return rt;
151         else if(x<rt->data)rt=rt->lc;
152         else rt=rt->rc;
153     }
154     return NULL;
155 }
156 node *erase(node *x){
157     if(x->lc&&x->rc){
158         node *y=findmax(x->lc);
159         x->data=y->data;
160         return erase(y);
161     }
162     if(!x->lc&&!x->rc){
163         if(x->prt){
164             if(x==x->prt->lc)x->prt->lc=NULL;
165             else x->prt->rc=NULL;
166         }
167         else root[T]=NULL;
168     }
169     else if(x->lc&&!x->rc){
170         x->lc->prt=x->prt;
171         if(x->prt){
172             if(x==x->prt->lc)x->prt->lc=x->lc;
173             else x->prt->rc=x->lc;
174         }
175         else root[T]=x->lc;
176     }
177     else if(!x->lc&&x->rc){
178         x->rc->prt=x->prt;
179         if(x->prt){
180             if(x==x->prt->lc)x->prt->lc=x->rc;
181             else x->prt->rc=x->rc;
182         }
183         else root[T]=x->rc;
184     }
185     node *rt=x->prt;
186     delete x;
187     x=NULL;
188     for(;rt;rt=rt->prt){
189         rt->refresh();
190         if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
191     }
192     return x;
193 }
194 node *findmax(node *x){
195     while(x->rc)x=x->rc;
196     return x;
197 }
198 void rebuild(node *rt){
199     cnt=0;
200     zorder(rt);
201     node *x=rebuild(1,cnt);
202     x->prt=rt->prt;
203     if(rt->prt){
204         if(rt==rt->prt->lc)rt->prt->lc=x;
205         else rt->prt->rc=x;
206     }
207     else root[T]=x;
208     removetree(rt);
209 }
210 void removetree(node *x){
211     if(!x)return;
212     removetree(x->lc);
213     removetree(x->rc);
214     delete x;
215 }
216 void zorder(node *x){
217     if(!x)return;
218     zorder(x->lc);
219     data[++cnt]=x->data;
220     zorder(x->rc);
221 }
222 node *rebuild(int l,int r){
223     if(l>r)return NULL;
224     int mid=(l+r)>>1;
225     node *x=new node(data[mid]);
226     x->lc=rebuild(l,mid-1);
227     if(x->lc)x->lc->prt=x;
228     x->rc=rebuild(mid+1,r);
229     if(x->rc)x->rc->prt=x;
230     x->refresh();
231     return x;
232 }
View Code

【后记】

这个题是用CDQ+树状数组水掉三维偏序之后的脑洞的产物……貌似在报复社会……

自己真是玩疯了……

posted @ 2016-10-08 17:17  AntiLeaf  阅读(296)  评论(0编辑  收藏  举报