首页 > 代码库 > COGS 2479 偏序 题解
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=http://www.mamicode.com/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 }
【后记】
这个题是用CDQ+树状数组水掉三维偏序之后的脑洞的产物……貌似在报复社会……
自己真是玩疯了……
COGS 2479 偏序 题解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。