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 }
【后记】
这个题是用CDQ+树状数组水掉三维偏序之后的脑洞的产物……貌似在报复社会……
自己真是玩疯了……
233333333